www.pudn.com > SBDcode.rar > CutDetector.cpp
/* * Copyright (c) 2003, Jim Easterbrook * * * This file is part of shot-change. * * shot-change is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * shot-change 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with shot-change; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #pragma comment(exestr,"$Id: CutDetector.cpp,v 1.1.1.1 2003/03/20 11:49:01 easter Exp $") /* * $Log: CutDetector.cpp,v $ * Revision 1.1.1.1 2003/03/20 11:49:01 easter * Initial import * */ #include// DirectShow (includes windows.h) #include // for VIDEOINFOHEADER2 #include #include #include "CutDetector.h" // setup data for self-registration static const WCHAR g_wszName[] = L"Cut Detector"; const AMOVIESETUP_MEDIATYPE sudVideoTypes[] = { { &MEDIATYPE_Video, &MEDIASUBTYPE_YUY2 }, }; const AMOVIESETUP_MEDIATYPE sudTextTypes[] = { { &MEDIATYPE_Text, &MEDIASUBTYPE_NULL }, }; const AMOVIESETUP_PIN psudPins[] = { { L"Video in", // strName (obsolete) FALSE, // bRendered FALSE, // bOutput FALSE, // bZero FALSE, // bMany &CLSID_NULL, // clsConnectsToFilter (obsolete) L"", // strConnectsToPin (obsolete) sizeof(sudVideoTypes)/sizeof(sudVideoTypes[0]), sudVideoTypes // lpTypes }, { L"~Video loop thru", // strName (obsolete) FALSE, // bRendered TRUE, // bOutput FALSE, // bZero FALSE, // bMany &CLSID_NULL, // clsConnectsToFilter (obsolete) L"", // strConnectsToPin (obsolete) sizeof(sudVideoTypes)/sizeof(sudVideoTypes[0]), sudVideoTypes // lpTypes }, { L"Text out", // strName (obsolete) FALSE, // bRendered TRUE, // bOutput FALSE, // bZero FALSE, // bMany &CLSID_NULL, // clsConnectsToFilter (obsolete) L"", // strConnectsToPin (obsolete) sizeof(sudTextTypes)/sizeof(sudTextTypes[0]), sudTextTypes // lpTypes }, }; const AMOVIESETUP_FILTER sudCutDetector = { &CLSID_CutDetector, // clsID g_wszName, // strName MERIT_DO_NOT_USE, // dwMerit sizeof(psudPins)/sizeof(psudPins[0]), psudPins // lpPin }; class VideoInPin : public CBaseInputPin { public: VideoInPin(CBaseFilter *pFilter, CCritSec *pLock, HRESULT *phr); private: STDMETHODIMP EndOfStream(void); STDMETHODIMP BeginFlush(void); STDMETHODIMP EndFlush(void); STDMETHODIMP Receive(IMediaSample *pSample); HRESULT SetMediaType(const CMediaType *pmt); HRESULT CheckMediaType(const CMediaType *pmt); HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); HRESULT CompleteConnect(IPin *pReceivePin); STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly); public: IMemAllocator* PeekAllocator(void) const { return m_pAllocator; } CMediaType CurrentMediaType(void) const { return m_mt; } private: CCritSec StreamLock; }; class QueuedOutputPin : public CBaseOutputPin { public: QueuedOutputPin(TCHAR *pObjectName, CBaseFilter *pFilter, CCritSec *pLock, HRESULT *phr, LPCWSTR pName); private: HRESULT Active(); HRESULT Inactive(); public: HRESULT Deliver(IMediaSample *pMediaSample); HRESULT DeliverEndOfStream(); HRESULT DeliverBeginFlush(); HRESULT DeliverEndFlush(); private: COutputQueue* pOutputQueue; }; class VideoOutPin : public QueuedOutputPin { public: VideoOutPin(CBaseFilter *pFilter,CCritSec *pLock, HRESULT *phr); private: HRESULT DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc); HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); HRESULT CheckMediaType(const CMediaType *pmt); HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); HRESULT CompleteConnect(IPin *pReceivePin); STDMETHODIMP Notify(IBaseFilter *pSender, Quality q); public: CMediaType CurrentMediaType(void) const { return m_mt; } }; class TextOutPin : public QueuedOutputPin { public: TextOutPin(CBaseFilter *pFilter,CCritSec *pLock, HRESULT *phr); private: HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); HRESULT CheckMediaType(const CMediaType *pmt); HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); STDMETHODIMP Notify(IBaseFilter *pSender, Quality q); }; // This class converts DirectShow sample times to frame numbers. This should be as easy as // dividing by the frame duration, but unfortunately the frame duration is not exactly as // reported by the AvgTimePerFrame video info header parameter. (Probably a consequence of // adjusting the video to fit the [free running] audio during capture.) This class attempts // to measure the actual frame time, and uses that to compute frame number. class ConvertSampleTime { public: ConvertSampleTime(); void ReStart(); void SetMediaType(const AM_MEDIA_TYPE *pmt); int GetFrameNo(IMediaSample *pSample); private: inline REFERENCE_TIME rdiv(const REFERENCE_TIME a, const REFERENCE_TIME b); private: #define TimeScale 100000 REFERENCE_TIME FrameDuration; REFERENCE_TIME LastStartTime; REFERENCE_TIME RefTime; REFERENCE_TIME RefFrame; REFERENCE_TIME FrameCount; REFERENCE_TIME TimeOffset; REFERENCE_TIME FDError; }; struct CDParams { CallBackFunc *pCallBack; float Threshold; }; class CCutDetector : public CBaseFilter, public IAMFilterMiscFlags, public ICDControl { public: static CUnknown *WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr); private: DECLARE_IUNKNOWN; STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv); // CBaseFilter stuff CCutDetector(LPUNKNOWN lpunk, HRESULT *phr); ~CCutDetector(); CBasePin *GetPin(int n); int GetPinCount(void); // IAMFilterMiscFlags stuff ULONG __stdcall GetMiscFlags(void); // ICDControl stuff STDMETHODIMP SetCallBack(CallBackFunc *pCallBack); STDMETHODIMP SetThreshold(const float Threshold); // My stuff public: HRESULT EndOfStream(void); HRESULT DeliverBeginFlush(void); HRESULT DeliverEndFlush(void); void ReleaseSamples(void); HRESULT SetMediaType(const AM_MEDIA_TYPE *pmt); HRESULT Receive(IMediaSample *pThisFrame); private: //HRESULT SendResult(const int FrameNo, const float Confidence, const int Duration); HRESULT SendResult(const int FrameNo, const int f1,const float f2,const float f3,const float f4,const float I1,const float I2,const float I3,const float I4); private: CCritSec StateLock; TextOutPin *pTextOutput; VideoInPin *pVideoInput; VideoOutPin *pVideoOutput; IMediaSample *pLastFrame; ConvertSampleTime CST; CDParams Params; // Image dimensions int xLen, yLen; int BytesPerLine; int SampleOffset; // Cut detector state int ValidFrames; // frames since sequence or segment started double b0[2],b1[2],accum0[2],accum1[2],accum3[2],accum4[2]; // double Grate[10]; // raw "cut" signal // double MAD[10]; // mean absolute difference // double Thresh[10]; // threshold based on local activity int frameno[3]; double C1[10]; //一次帧差;; double Grate[10]; //平均灰度; double D_hist[256]; //直方图差; double D_hist_2[256]; double mono[256];//单色 long int startNO[2],EndNO[2],signNO[2]; long int dowmNO[2],upNO[2] ,accum_mono[2]; double LHIST[256][10]; int cnt; double acc_hist; double level; double savec1[256],savedhist[256],savemono[256]; double SS1[10],SS2[10],SS3[10],SS[10],DS[10]; int a0,a1; // symbol bits; }; // Global variables used by the class factory CFactoryTemplate g_Templates[]= { { g_wszName, &CLSID_CutDetector, CCutDetector::CreateInstance, NULL, &sudCutDetector } }; int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]); // Create and return an instance of the filter CUnknown *WINAPI CCutDetector::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr) { CUnknown *punk = new CCutDetector(lpunk, phr); if (punk == NULL) *phr = E_OUTOFMEMORY; return punk; } STDMETHODIMP CCutDetector::NonDelegatingQueryInterface(REFIID riid, void **ppv) { CheckPointer(ppv, E_POINTER); if (riid == IID_IAMFilterMiscFlags) return GetInterface((IAMFilterMiscFlags*)this, ppv); if (riid == IID_ICDControl) return GetInterface((ICDControl*)this, ppv); return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); } CCutDetector::CCutDetector(LPUNKNOWN punk, HRESULT *phr) : CBaseFilter(NAME("cut detector"), punk, &StateLock, CLSID_CutDetector) { pVideoInput = new VideoInPin(this, m_pLock, phr); pVideoOutput = new VideoOutPin(this, m_pLock, phr); pTextOutput = new TextOutPin(this, m_pLock, phr); if (pVideoInput == NULL || pVideoOutput == NULL || pTextOutput == NULL) *phr = E_OUTOFMEMORY; pLastFrame = NULL; Params.pCallBack = NULL; Params.Threshold = 0.0; } // Destructor CCutDetector::~CCutDetector() { delete pVideoInput; delete pVideoOutput; delete pTextOutput; // Release any left over samples if (pLastFrame != NULL) { pLastFrame->Release(); pLastFrame = NULL; } } #define VideoInputNo 0 #define VideoOutputNo 1 #define TextOutputNo 2 CBasePin* CCutDetector::GetPin(int n) { if (n == VideoInputNo) return pVideoInput; if (n == VideoOutputNo) return pVideoOutput; if (n == TextOutputNo) return pTextOutput; return NULL; } int CCutDetector::GetPinCount(void) { return 3; } ULONG __stdcall CCutDetector::GetMiscFlags(void) { if (pVideoOutput->IsConnected() || pTextOutput->IsConnected()) return 0; else return AM_FILTER_MISC_FLAGS_IS_RENDERER; } STDMETHODIMP CCutDetector::SetCallBack(CallBackFunc *pCallBack) { Params.pCallBack = pCallBack; return S_OK; } STDMETHODIMP CCutDetector::SetThreshold(const float Threshold) { Params.Threshold = Threshold; return S_OK; } HRESULT CCutDetector::EndOfStream(void) { HRESULT hr; if (pVideoOutput->IsConnected()) { hr = pVideoOutput->DeliverEndOfStream(); if (FAILED(hr)) return hr; } if (pTextOutput->IsConnected()) { hr = pTextOutput->DeliverEndOfStream(); if (FAILED(hr)) return hr; } if ((GetMiscFlags() & AM_FILTER_MISC_FLAGS_IS_RENDERER) != 0) { // Send an EC_COMPLETE event to stop the graph hr = NotifyEvent(EC_COMPLETE, 0, 0); if (FAILED(hr)) return hr; } return S_OK; } HRESULT CCutDetector::DeliverBeginFlush(void) { HRESULT hr; if (pVideoOutput->IsConnected()) { hr = pVideoOutput->DeliverBeginFlush(); if (FAILED(hr)) return hr; } if (pTextOutput->IsConnected()) { hr = pTextOutput->DeliverBeginFlush(); if (FAILED(hr)) return hr; } return S_OK; } HRESULT CCutDetector::DeliverEndFlush(void) { HRESULT hr; if (pVideoOutput->IsConnected()) { hr = pVideoOutput->DeliverEndFlush(); if (FAILED(hr)) return hr; } if (pTextOutput->IsConnected()) { hr = pTextOutput->DeliverEndFlush(); if (FAILED(hr)) return hr; } return S_OK; } void CCutDetector::ReleaseSamples(void) { if (pLastFrame != NULL) { pLastFrame->Release(); pLastFrame = NULL; } } HRESULT CCutDetector::SetMediaType(const AM_MEDIA_TYPE *pmt) { BITMAPINFOHEADER *pBmi; RECT *pSrcRect; CST.SetMediaType(pmt); if (pmt->formattype == FORMAT_VideoInfo) { pSrcRect = &((VIDEOINFOHEADER*)pmt->pbFormat)->rcSource; pBmi = &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader; } else if (pmt->formattype == FORMAT_VideoInfo2) { pSrcRect = &((VIDEOINFOHEADER2*)pmt->pbFormat)->rcSource; pBmi = &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader; } else return E_UNEXPECTED; BytesPerLine = (int)pBmi->biSizeImage / abs(pBmi->biHeight); xLen = pSrcRect->right - pSrcRect->left; if (xLen == 0) xLen = pBmi->biWidth; yLen = pSrcRect->bottom - pSrcRect->top; if (yLen == 0) yLen = abs(pBmi->biHeight); SampleOffset = (pSrcRect->top * BytesPerLine) + (pSrcRect->left * 2); return S_OK; } HRESULT CCutDetector::Receive(IMediaSample *pThisFrame) { HRESULT hr; int ThisFrameNo; int sk2,sk0,Xn,Yn,p0,p1; double p_this,p_last,p_diff,Tn; double danse; int tabs[710],tab0[710],tabn[710]; int CycNO; double n0,np,nn,p_0,p_n,p_p; danse=0.0; p_diff=0.0; CycNO=0; AM_MEDIA_TYPE *NewMT; if (pLastFrame == NULL) ValidFrames = 0; if (pThisFrame->GetMediaType(&NewMT) == S_OK) { ValidFrames = 0; hr = SetMediaType(NewMT); DeleteMediaType(NewMT); if (FAILED(hr)) return hr; } if (pThisFrame->IsDiscontinuity() == S_OK) { ValidFrames = 0; CST.ReStart(); } ThisFrameNo = CST.GetFrameNo(pThisFrame); ValidFrames = min(ValidFrames + 1, 100000); // Shift results from previous frame // memmove(&C0[1], &C0[0], sizeof(C0) - sizeof(C0[0])); memmove(&C1[1], &C1[0], sizeof(C1) - sizeof(C1[0])); // memmove(&MAD[1], &MAD[0], sizeof(MAD) - sizeof(MAD[0])); // memmove(&Gdiff[1], &Gdiff[0], sizeof(Gdiff) - sizeof(Gdiff[0])); memmove(&Grate[1], &Grate[0], sizeof(Grate) - sizeof(Grate[0])); // memmove(&Thresh[1], &Thresh[0], sizeof(Thresh) - sizeof(Thresh[0])); memmove(&D_hist[1], &D_hist[0], sizeof(D_hist) - sizeof(D_hist[0])); memmove(&D_hist_2[1], &D_hist_2[0], sizeof(D_hist_2) - sizeof(D_hist_2[0])); memmove(&mono[1], &mono[0], sizeof(mono) - sizeof(mono[0])); memmove(&startNO[1], &startNO[0], sizeof(startNO) - sizeof(startNO[0])); memmove(&EndNO[1], &EndNO[0], sizeof(EndNO) - sizeof(EndNO[0])); memmove(&signNO[1], &signNO[0], sizeof(signNO) - sizeof(signNO[0])); memmove(&SS1[1], &SS1[0], sizeof(SS1) - sizeof(SS1[0])); memmove(&SS2[1], &SS2[0], sizeof(SS2) - sizeof(SS2[0])); memmove(&SS3[1], &SS3[0], sizeof(SS3) - sizeof(SS3[0])); memmove(&SS[1], &SS[0], sizeof(SS) - sizeof(SS[0])); memmove(&DS[1], &DS[0], sizeof(DS) - sizeof(DS[0])); for(int i = 0; i <= 255; i++) { memmove(& LHIST[i][1], & LHIST[i][0], sizeof( LHIST[i]) - sizeof( LHIST[i][0])); } if (ValidFrames >= 2) { // Compute mean absolute interframe difference BYTE *pThisLine, *pLastLine,*pThisLine0, *pLastLine0; BYTE *pThisSample, *pLastSample; int Total; hr = pThisFrame->GetPointer(&pThisLine); if (FAILED(hr)) return hr; hr = pLastFrame->GetPointer(&pLastLine); if (FAILED(hr)) return hr; pThisLine0 = pThisLine + SampleOffset; pLastLine0 = pLastLine + SampleOffset; Total = 0; D_hist[0] = 0; D_hist_2[0] = 0; n0=np=nn=p_0=p_n=p_p=0.0; p_this=p_last=p_diff=0.0; sk0=1; sk2=2*sk0; Xn=int(xLen /sk0); Yn=int((yLen)/(sk0)); Tn=double(Yn*Xn); pThisLine=pThisLine0; pLastLine=pLastLine0; for (int y = 0; y < Yn; y++) { pThisSample = pThisLine; pLastSample = pLastLine; for (int x = 0; x < Xn; x++) { p0 = (*pLastSample); p1 = (*pThisSample); LHIST[p1][0] += 1; p_this=p_this+ double (p1); if (p0==p1) //不变; { p_0 += 1.0; // n0=n0+1.0; } else { if (p1>p0) //减小; { p_p +=(double) p0/(double)p1; // np=np+1.0; } else //增大; { p_n += (double)p1/(double)p0; // nn=nn+1.0; } } pThisSample = pThisSample + sk2; // Skip U or V sample pLastSample = pLastSample + sk2; } pThisLine = pThisLine + BytesPerLine; pLastLine = pLastLine + BytesPerLine; } Grate[0]=p_this/Tn; //平均灰度; for( int j = 0; j <= 255;j++) //灰度直方图; { LHIST[j][0] = LHIST[j][0]/Tn; } for( int k = 0; k <= 255; k++) //帧间差(1); { D_hist[0] += fabs( LHIST[k][0] - LHIST[k][1]); D_hist_2[0] += fabs( LHIST[k][0] - LHIST[k][3]); } if(D_hist_2[0] < 0.2 && D_hist_2[1] > 0.5 && D_hist_2[2] < 0.2) { D_hist[0] = 0.01; D_hist[1] = 0.01; } SS1[0]= p_0/(Tn); SS2[0]= p_p/(Tn); SS3[0]= p_n/(Tn); SS[0] = SS1[0] +SS2[0] + SS3[0]; //总的相似度; DS[0] = (1-exp(-10*(1-SS[0]))); //差异度; pThisLine=pThisLine0; pLastLine=pLastLine0; // for (y = 0; y < Yn; y++) { pThisSample = pThisLine; pLastSample = pLastLine; for (int x = 0; x < Xn; x++) { p0=(*pLastSample); p1=(*pThisSample); //求单色帧 danse=danse+fabs((p1)-Grate[0]); p_diff=p_diff+fabs(p1-Grate[0]-p0+Grate[1]); pThisSample = pThisSample + sk2; // Skip U or V sample pLastSample = pLastSample + sk2; } pThisLine = pThisLine + BytesPerLine; pLastLine = pLastLine + BytesPerLine; } mono[0]=danse/Tn; //"方差"; C1[0]=p_diff/Tn; //一次帧差; } #pragma warning(push) #pragma warning(disable:4244) // turn off conversion from double to float warning // Convert to "confidence" and output result /********************打印镜头变化处数据 ********************/ // for ( int y = 1; y <=480; y++) /* for ( int y =124; y <=325; y++) //打印DISSOLVE; { if (ThisFrameNo >= tab0[y] - 2 && ThisFrameNo <= tab0[y]+tabn[y] + 3 && tabn[y]==2) { hr=SendResult(ThisFrameNo,0, Grate[0],C1[0], mono[0],D_hist[0],D_hist_2[0],SS1[0],DS[0]); break; } } */ /*************** FADE DETECTION *******************/ // /* if(ThisFrameNo >5 && mono[5] < 6.5 && (Grate[5] < 55.0 || Grate[5] > 177.0 )) //黑色,灰色; { accum_mono[0] += 1; //单色帧持续的周长; //找cut+fade in类型的OTHS起始位置; if ( mono[6] > 6.5 && C1[5] >= 17.0) { startNO[0] = ThisFrameNo-6; a0 = 1; } // FADE OUT 找起始位置; if (( mono[6] > 6.5 ||(mono[6] < 6.5 && Grate[6] > 55.0 && Grate[6] < 100.0) ||(mono[6] < 6.5 && Grate[6] > 155.0 && Grate[6] < 177.0)) && C1[5] < 17.0) { accum0[0] = accum1[0]=0; dowmNO[0] = upNO[0] = 0; for(int i=0 ; ;i++) { if( mono[5+i] <= mono[6+i] && (mono[6+i]-mono[5+i]) < 5.0 && (mono[6+i]-mono[5+i]) >= 0.3 //momo分布曲线单调递减,没有突变。 ) { accum1[0] += 1; if(accum0[0]==1) { accum0[0] =0; } } if( (mono[5+i] > mono[6+i]) ||((mono[6+i]-mono[5+i]) < 0.3 && (mono[6+i]-mono[5+i]) >= 0 )) //累计奇异点的个数; { accum0[0] +=1; } CycNO += 1; //循环次数; if(accum0[0] >=2) //连续出现两个奇异点就终止搜索起始边界; break; } startNO[0] = ThisFrameNo-5-(CycNO-2); } //背景很暗的FADE if(mono[6] < 6.5 && mono[5] < 6.5 && mono[4] < 6.5) { if( mono[5] <= mono[4] ) //递增; { dowmNO[0] = 0 ; upNO[0] += 1; if(upNO[0] >= 7 ) { if(mono[3] < mono[4] && mono[3] < 6.5 && accum_mono[0] >= 12) { EndNO[0] = ThisFrameNo - 5; if((EndNO[0] - startNO[0]) > 2 && (EndNO[0] - startNO[0]) <=128) { hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); dowmNO[0] = upNO[0] = 0; EndNO[0] = startNO[0] = 0; } } } } if( mono[5] > mono[4]) //递减; { upNO[0] = 0 ; dowmNO[0] += 1; if(dowmNO[0] == 7 && accum_mono[0] >= 12) { startNO[0] = ThisFrameNo - 12; } } } } // //fade out + cut 类型的OTHS的终止边界; if( mono[5] < 6.5 && mono[4] > 6.5 && (Grate[5] < 55.0 || Grate[5] > 180.0) && C1[4] >= 17.0) { EndNO[0] = ThisFrameNo-4; a1 = 1; if((EndNO[0] - startNO[0]) > 2 && (EndNO[0] - startNO[0]) <=128) { if(a0==1 && a1 ==1 && accum_mono[0] >= 2) { hr=SendResult(startNO[0] ,startNO[0]+1,0,0,0,0,0,0,0); hr=SendResult(EndNO[0]-1 ,EndNO[0],0,0,0,0,0,0,0); } else hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); } a0 = 0; a1 = 0; } // //找fade in 的终止边界; if( mono[5] < 6.5 &&( mono[4] > 6.5 && (Grate[5] < 55.0 || Grate[5] > 177.0) ||( mono[4] < 6.5 && Grate[4] > 55.0 && Grate[4] < 100.0) ||( mono[4] < 6.5 && Grate[4] > 155.0 && Grate[4] < 177.0)) && C1[4] < 17.0) { accum_mono[0] =0; b0[0] = mono[5]; b1[0] = mono[4]; accum0[0]=accum1[0]=0; } if( ThisFrameNo >7 && b0[0] < 6.5 && b1[0] > 6.5 ) { if( mono[5] <= mono[4] && (mono[4]-mono[5]) < 5.0 && (mono[4]-mono[5]) >= 0.3) { accum1[0] += 1; if(accum0[0] ==1) { accum0[0] =0; } } if((mono[5] > mono[4]) ||((mono[4]-mono[5]) < 0.3 && (mono[4]-mono[5]) >= 0 ))//|| ((mono[4]-mono[5]) > 10.0)) { accum0[0] +=1; } if(accum0[0] >=2) { EndNO[0] = ThisFrameNo-7; b0[0] =b1[0] = 0.0; //fade 结束时清零; if((EndNO[0] - startNO[0]) > 2 && (EndNO[0] - startNO[0]) <=128) { hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); } } } */ /************* CUT DETECTION*****************/ //特征:相异度DS; if( ThisFrameNo >7 && mono[3] > 6.5 && mono[4] >= 6.5 // eliminate 单色帧 && DS[3] == max(max(max(max(max(max(DS[0],DS[1]),DS[2]),DS[3]),DS[4]),DS[5]),DS[6]) ) { // if(DS[3] >= 0.90 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) <= 0.7 && DS[3] >= 1.40* max(DS[4],DS[2]) ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,DS[6],DS[5],DS[4],DS[3],DS[2],DS[1],DS[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } // else if( DS[3] >= 0.80 && DS[3] < 0.90 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) <= 0.50 && DS[3] >= 2.10* max(DS[4],DS[2]) ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,DS[6],DS[5],DS[4],DS[3],DS[2],DS[1],DS[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } // else if(DS[3] >= 0.95 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) > 0.70 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) <= 0.80 && DS[3] >= 1.23*max(DS[4],DS[2]) ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,DS[6],DS[5],DS[4],DS[3],DS[2],DS[1],DS[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } // else if(DS[3] >= 0.95 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) > 0.80 && max(max(max(DS[1],DS[2]),DS[4]),DS[5]) <= 0.90 && DS[3] >= 1.12*max(DS[4],DS[2]) ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,DS[6],DS[5],DS[4],DS[3],DS[2],DS[1],DS[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } } //特征:一次帧差C1; /* double Mean_0,Mean_1,Mean_2; Mean_0 = (C1[0]+C1[1]+C1[2]+C1[4]+C1[5]+C1[6])/6.0; Mean_1 = (C1[1]+C1[2]+C1[4]+C1[5])/4.0; Mean_2 = (C1[2]+C1[4])/2.0; if( ThisFrameNo >7 && Grate[3] >= 35.0 && Grate[4] >= 35.0 // eliminate 单色帧 ) { // if(C1[3] >= 35.0) { if( Mean_0 <= 10.5 && Mean_1 <= 10.5 && Mean_2 <= 10.5 && C1[3] >= 5.0*Mean_0 && C1[3] >= 5.1*Mean_1 && C1[3] >= 4.9*Mean_2 && C1[3] >= 3.9*max(C1[2],C1[4])//3.9 ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3, D_hist[6],D_hist[5],D_hist[4],D_hist[3],D_hist[2],D_hist[1],D_hist[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } } // else if(C1[3] >= 20.0 && C1[3] < 35.0) { if( Mean_0 <= 4.5 && Mean_1 <= 4.9 && Mean_2 <= 6.1 && C1[3] >= 5.4*Mean_0 && C1[3] >= 4.4*Mean_1 && C1[3] >= 5.3*Mean_2 && C1[3] >= 3.4*max(C1[2],C1[4]) ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,D_hist[6],D_hist[5],D_hist[4],D_hist[3],D_hist[2],D_hist[1],D_hist[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } } // else if( C1[3] >= 10.0 && C1[3] < 20.0) { if( Mean_0 <= 3.4 && Mean_1 <= 3.8 && Mean_2 <= 4.3 && C1[3] >= 4.8*Mean_0 && C1[3] >= 4.5*Mean_1 && C1[3] >= 4.0*Mean_2 && C1[3] >= 3.3*max(C1[2],C1[4])//5.2 ) { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } } } */ /**********2_LEN dissolve detection *****************/ //特征:相异度,灰度直方图差,一次帧差; /* double Mean_DS,Mean_Dhist,Mean_C1; Mean_DS = (DS[0] + DS[1] + DS[2] + DS[5] + DS[6] + DS[7] )/6; Mean_Dhist = (D_hist[0] + D_hist[1] + D_hist[2] + D_hist[5] + D_hist[6] + D_hist[7] )/6; Mean_C1 = (C1[0] + C1[1] + C1[2] + C1[5] + C1[6] + C1[7] )/6; if( ThisFrameNo >7 // && Grate[2] > 35.0 && Grate[3] > 35.0 && Grate[4] > 35.0 && Grate[5] > 35.0 && Grate[6] > 35.0 // && min(DS[4],DS[3]) >= 0.45 && DS[3] == max(max(max(DS[0],DS[1]),DS[2]),DS[3]) && DS[4] == max(max(max(DS[4],DS[5]),DS[6]),DS[7]) && max(DS[4],DS[3]) <= 3.0 * min(DS[4],DS[3]) && min(DS[4],DS[3]) >= 1.5 * Mean_DS // && Mean_Dhist <= 0.2 && D_hist[3] == max(max(max(D_hist[0],D_hist[1]),D_hist[2]),D_hist[3]) && D_hist[4] == max(max(max(D_hist[4],D_hist[5]),D_hist[6]),D_hist[7]) && max(D_hist[4],D_hist[3]) <= 5.0 * min(D_hist[4],D_hist[3]) //系数2.0,3.5 && min(D_hist[4],D_hist[3]) >= 2.6 * Mean_Dhist //2.2 && (D_hist[3]+D_hist[4]) >= 0.68 //0.45 &&min(min(min( D_hist_2[1],D_hist_2[2]),D_hist_2[3]),D_hist_2[4]) >= 0.20 // eliminate Flash; // // && Mean_C1 <= 7.0 //5.0 // && C1[3] == max(max(max(C1[0],C1[1]),C1[2]),C1[3]) // && C1[4] == max(max(max(C1[4],C1[5]),C1[6]),C1[7]) // && max(C1[4],C1[3]) <= 4.8 * min(C1[4],C1[3]) //系数4.0 // && min(C1[4],C1[3]) >= 1.7 * Mean_C1 ) { if(Grate[4]-Grate[5] > 9.0 && Grate[4]-Grate[3] > 9.0) // eliminate Flash; { if( D_hist_2[2] >= 0.85 && D_hist_2[3] >= 0.85 && D_hist_2[4] >= 0.85 && D_hist_2[5] <= 0.1) //flash occurs during a cut; { hr=SendResult(ThisFrameNo-5,ThisFrameNo-4,C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-5,34,34,ThisFrameNo-4,34); } else //flash; ; } else { hr=SendResult(ThisFrameNo-5,ThisFrameNo-3, C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,68,34,34,ThisFrameNo-5,34,34,ThisFrameNo-3,34); } } else if ( D_hist[4] >= 0.2 && D_hist[3] >= 0.2 && D_hist[4] + D_hist[3] >= 0.85 && D_hist[0] <= 0.1 && D_hist[1] <= 0.1 // && D_hist[2] <= 0.1 // && D_hist[5] <= 0.1 && D_hist[6] <= 0.1 && D_hist[7] <= 0.1 && Mean_Dhist <= 0.1 ) { if(Grate[4]-Grate[5] > 9.0 && Grate[4]-Grate[3] > 9.0) // eliminate Flash; { if( D_hist_2[2] >= 0.85 && D_hist_2[3] >= 0.85 && D_hist_2[4] >= 0.85 && D_hist_2[5] <= 0.1) //flash occurs during a cut; { hr=SendResult(ThisFrameNo-5,ThisFrameNo-4,C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-5,34,34,ThisFrameNo-4,34); } else //flash; ; } // else if( (max(C1[3],C1[4]) >= 9.0*min(C1[3],C1[4]) && max(C1[5],C1[4]) >= 9.0*min(C1[5],C1[4])) ||(max(C1[3],C1[2]) >= 9.0*min(C1[3],C1[2]) && max(C1[3],C1[4]) >= 9.0*min(C1[3],C1[4])) ) // eliminate cut; { if(max(C1[3],C1[4]) == C1[4]) { hr=SendResult(ThisFrameNo-5,ThisFrameNo-4,C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-5,34,34,ThisFrameNo-4,34); } else { hr=SendResult(ThisFrameNo-4,ThisFrameNo-3,C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); // hr=SendResult(34,67,34,34,ThisFrameNo-4,34,34,ThisFrameNo-3,34); } } // else hr=SendResult(ThisFrameNo-5,ThisFrameNo-3, C1[6],C1[5],C1[4],C1[3],C1[2],C1[1],C1[0]); } */ /* //afanty's code: if ( C1[5]>=20.0&& C1[4]>=20.0 && C1[3]<=4.1&& C1[2]<=4.8 && C1[6]<=2.77 && C1[7]<=3.8 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && C1[5]>C1[6] && C1[4]>C1[3] && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[5]<20.0 && C1[5]>10.0 && C1[4]<20.0 && C1[4]>10.0 && C1[3]<=3.5 && (C1[2]<=2.9 || fabs(Grate[1]-Grate[3])<2.0)//防止闪光 && C1[6]<=6.1 && (C1[7]<=6.64|| fabs(Grate[6]-Grate[8])<2.0) && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && C1[5]>C1[6] && C1[4]>C1[3] && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[5]<10.0 && C1[5]>4.3 && C1[4]<10.0 && C1[4]>4.3 && C1[3]<=2.76 && (C1[2]<=2.5 || fabs(Grate[1]-Grate[3])<2.0)//防止闪光 && C1[6]<=2.76 && (C1[7]<=3.3|| fabs(Grate[6]-Grate[8])<2.0) && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && C1[5]>C1[6] && C1[4]>C1[3] && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[5]>20.0 && C1[4]<20.0 && C1[4]>10.0 && C1[5]>C1[6] && C1[4]>C1[3] && (C1[3]<6.1||fabs(C1[3]-C1[2])<2.0)//防止晃动 && (C1[6]<5.2||fabs(C1[6]-C1[7])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[4]>20.0 && C1[5]<20.0 && C1[5]>10.0 && C1[5]>C1[6] && C1[4]>C1[3] && (C1[6]<6.1||fabs(C1[6]-C1[7])<2.0)//防止晃动 && (C1[3]<5.2||fabs(C1[3]-C1[2])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[5]<20.0 && C1[5]>10.0 && C1[5]-C1[6]>5.0 && C1[4]>C1[3] && C1[4]<10.0 && C1[4]>4.0 && (C1[3]<4.4||fabs(C1[3]-C1[2])<2.0)//防止晃动 && (C1[6]<2.8||fabs(C1[6]-C1[7])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[4]<20.0 && C1[4]>10.0 && C1[4]-C1[3]>5.0 && C1[5]>C1[6] && C1[5]<10.0 && C1[5]>4.0 && (C1[6]<4.4||fabs(C1[6]-C1[7])<2.0)//防止晃动 && (C1[3]<2.8||fabs(C1[3]-C1[2])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[5]>20.0 && C1[4]<10.0 && C1[4]>4.0 && C1[5]-C1[6]>5.0 && C1[4]>C1[3] && (C1[6]<6.7||fabs(C1[6]-C1[7])<2.0)//防止晃动 && (C1[3]<4.2||fabs(C1[3]-C1[2])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); else if ( C1[4]>20.0 && C1[5]<10.0 && C1[5]>4.0 && C1[4]-C1[3]>5.0 && fabs(C1[5]-C1[6])>1.5 && (C1[3]<6.7||fabs(C1[3]-C1[2])<2.0)//防止晃动 && (C1[6]<4.2||fabs(C1[6]-C1[7])<2.0)//防止晃动 && fabs(Grate[7]-Grate[2])>2.2//防止闪光 && mono[6]>6.5 &&mono[5]>6.5&&mono[4]>6.5&&mono[3]>6.5 ) hr=SendResult(ThisFrameNo-5-1,ThisFrameNo-5+1,0,0,0,0,0,0,0); // hr=SendResult(34,68,34,34,ThisFrameNo-6,34,34,ThisFrameNo-4,34); */ /****** short gradual transition detection **********/ //用的特征是灰度直方图差 D_hist[0]; /* if( D_hist[5] >= 0.1 && D_hist[5] < 0.85 && C1[5] >= 4.0 && D_hist[6] < 0.08 && D_hist[5] / D_hist[6] >= 2.3 && mono[5] > 10.0 && cnt == 0 ) { cnt += 1; acc_hist += D_hist[5]; } else if ( D_hist[5] >= 0.1 && D_hist[5] < 0.85 && D_hist[6] >= 0.1 && D_hist[6] < 0.85 && C1[5] >= 4.0 && (max(C1[5],C1[6])/min(C1[5],C1[6])) <= 4.0 && (max(D_hist[5],D_hist[6])/min(D_hist[5],D_hist[6])) <= 3.0 && mono[5] > 10.0 && cnt >= 1 ) { cnt += 1; acc_hist += D_hist[5]; } else { if(D_hist[5] >= 0.85) ; else if( cnt > 2 && cnt < 8 && acc_hist >= 0.85 && mono[5] > 10.0) //检测部分短渐变; { for ( int i = 0; i < cnt; i++) { savemono[i]= mono[cnt + 5 - i]; } double MINMONO; MINMONO=100.0; int SignNO; for( i = 0; i < cnt; i++) { MINMONO =min(MINMONO,savemono[i]); } for(i = 0; i < cnt; i++) { if(savemono[i] == MINMONO) { SignNO = i; break; } } int acc_odd; acc_odd=0; for( i = 0;i < SignNO; i++) { if(savemono [i] < savemono[i+1]) { acc_odd += 1; } } for( i = SignNO+1;i < cnt; i++) { if(savemono [i-1] > savemono[i]) { acc_odd += 1; } } if(acc_odd == 0 && mono[7] < mono[6] ) { if(mono[5] < mono[4] && mono[4] < mono[3] && fabs(mono[5]-mono[6]) < 0.3 ) ; else if(mono[5] > mono[4] && mono[4] > mono[3] && fabs(mono[5]-mono[6]) < 0.3 ) ; else if(mono[5+cnt+2] > mono[5+cnt+1] && mono[5+cnt+1] > mono[5+cnt] && fabs(mono[5+cnt+1]-mono[5+cnt]) < 0.3 ) ; else if(mono[5+cnt+2] < mono[5+cnt+1] && mono[5+cnt+1] < mono[5+cnt] && fabs(mono[5+cnt+1]-mono[5+cnt]) < 0.3 ) ; else hr=SendResult(ThisFrameNo-5-cnt-1,ThisFrameNo-5-1,0,0,0,0,0,0,0); } } cnt = 0; acc_hist = 0; } */ /**************** DISSOLVE DETECTION *****************/ /* int SignNO; double threshold; threshold = 0.07; //start; if( C1[5] <= 20.0 && D_hist[5] >= threshold && cnt == 0 ) { if( fabs( mono[6]- mono[5]) >= 0.3 ) cnt = 1; else cnt = 0; } // else if( C1[5] <= 20.0 && D_hist[6] >= threshold && D_hist[5] >= threshold && cnt >= 1) { cnt += 1; } //tolerance one singular point; else if( C1[5] <= 20.0 && D_hist[6] >= threshold && D_hist[5] < threshold && D_hist[4] >= threshold && D_hist[3] >= threshold && cnt >= 1) { cnt += 1; } // else if( C1[5] <= 20.0 && D_hist[7] >= threshold && D_hist[6] < threshold && D_hist[5] >= threshold && D_hist[4] >= threshold && cnt >= 1) { cnt += 1; } //end; else if( ( C1[5] <= 20.0 && D_hist[7] >= threshold && D_hist[6] >= threshold && D_hist[5] < threshold && D_hist[4] < threshold && cnt >= 1 ) ||( C1[5] <= 20.0 && D_hist[6] >= threshold && D_hist[5] < threshold && D_hist[4] >= threshold && D_hist[3] < threshold && cnt >= 1 ) ||( C1[5] > 20.0 && cnt >= 1 ) ) { // if(cnt >=8 && cnt <= 250) // hr=SendResult(ThisFrameNo-6-cnt,ThisFrameNo-5,0,0,0,0,0,0,0); // cnt = 0 ; if(cnt >=8 && cnt <= 250) { for ( int i = 0; i < cnt; i++) { savemono[i]= mono[cnt + 5 - i]; } double MINMONO; MINMONO=100.0; for( i = 0; i < cnt; i++) { MINMONO =min(MINMONO,savemono[i]); } for(i = 0; i < cnt; i++) { if(savemono[i] == MINMONO) { SignNO = i; break; } } if( SignNO <= 1) //单增; { startNO[0] = ThisFrameNo-6-cnt; for(i = 2; i < cnt-2; i++) { // if(savemono[i] >savemono[i+1] && savemono[i+1] < savemono[i+2]) // { // ac_odd += 1; // } if(savemono[i] >= savemono[i+1] && savemono[i+1] >= savemono[i+2]) { EndNO[0] = ThisFrameNo-5-cnt + i; break; } } if(EndNO[0]==0) EndNO[0] = ThisFrameNo-5; hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); EndNO[0] = startNO[0] = 0; cnt = 0; } else if(SignNO >= cnt-2) //单减; { EndNO[0] = ThisFrameNo - 5; for(i = cnt-2; i > 1; i--) { if(savemono[i] >= savemono[i-1] && savemono[i-1] >= savemono[i-2]) { startNO[0] = ThisFrameNo-6-cnt + i; break; } } if(startNO[0]==0) startNO[0] = ThisFrameNo-6-cnt; hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); EndNO[0] = startNO[0] = 0; cnt = 0; } else { for(i = SignNO; i > 1; i--) { if(savemono[i] >= savemono[i-1] && savemono[i-1] >= savemono[i-2]) { startNO[0] = ThisFrameNo-6-cnt + i; break; } } if(startNO[0]==0) startNO[0] = ThisFrameNo-6-cnt; for(i = SignNO; i < cnt-2;i++) { if(savemono[i] >= savemono[i+1] && savemono[i+1] >= savemono[i+2]) { EndNO[0] = ThisFrameNo-5-cnt + i; break; } } if(EndNO[0]==0) EndNO[0] = ThisFrameNo-5; hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); EndNO[0] = startNO[0] = 0; cnt = 0; } } else { cnt = 0; } } // else { cnt = 0; } */ /* if( Grate[5] >= 45.0 && C1[5] <= 20.0 && D_hist[5] >= 0.1) { if( mono[6] > mono[5]// && mono[5] > mono[4]) // ||(mono[6] < mono[5] && fabs(mono[6] - mono[5]) < 0.2 && mono[5] > mono[4]) ) //递减; { upNO[0] = 0 ; dowmNO[0] += 1; if( mono[5] < mono[4]// && mono[4] < mono[3] && D_hist[4] >= 0.1) { startNO[0] = (ThisFrameNo -5) - (dowmNO[0]) ; signNO[0] = ThisFrameNo -5; } } if(mono[6] <= mono[5] //&& mono[5] <= mono[4]) // ||(mono[6] > mono[5] && fabs(mono[6] - mono[5]) < 0.2 && mono[5] < mono[4]) ) //递增; { dowmNO[0] = 0 ; upNO[0] += 1; if( mono[5] >= mono[4] //&& mono[4] >= mono[3]) || D_hist[4] < 0.1 ) { EndNO[0] = ThisFrameNo - 5; } } } else { EndNO[0] = startNO[0] = 0; upNO[0] = dowmNO[0] = 0; } if( (EndNO[0] - startNO[0]) >= 8 && (EndNO[0] - startNO[0]) <= 128 && EndNO[0] - signNO[0] == upNO[0]) { hr=SendResult(startNO[0] ,EndNO[0],0,0,0,0,0,0,0); EndNO[0] = startNO[0] = 0; upNO[0] = dowmNO[0] = 0; } */ /* // 中间只出现一帧单色帧的OTH 检测(mono) if( mono[5] < 5.0 && mono[4] > 20.0 && mono[6] > 20.0 && (mono[4] > mono[3] || mono[6] > mono[7] ) //单色帧两侧 mono不满足单调性(区分FADE); ) hr=SendResult(ThisFrameNo-6,ThisFrameNo-4,0,0,0,0,0,0,0); // 中间只出现两帧单色帧的OTH 检测(mono) if( mono[5] < 5.0 && mono[4] < 5.0 && mono[3] > 20.0 && mono[6] > 20.0 && (mono[3] > mono[2] || mono[6] > mono[7] ) //单色帧两侧 mono不满足单调性(区分FADE); ) hr=SendResult(ThisFrameNo-6,ThisFrameNo-3,0,0,0,0,0,0,0); */ if (FAILED(hr)) return hr; #pragma warning(pop) // Release last sample if (pLastFrame != NULL) { pLastFrame->Release(); pLastFrame = NULL; } // Hold on to this sample pLastFrame = pThisFrame; pLastFrame->AddRef(); // Pass on video frame if (pVideoOutput->IsConnected()) { hr = pVideoOutput->Deliver(pThisFrame); if (FAILED(hr)) return hr; } return S_OK; } // HRESULT CCutDetector::SendResult(const int FrameNo, const float Confidence, const int Duration) HRESULT CCutDetector::SendResult(const int FrameNo, const int f1,const float f2,const float f3,const float f4,const float I1,const float I2,const float I3,const float I4) { IMediaSample *pOutput; char *pOutData; HRESULT hr = S_OK; if (pTextOutput->IsConnected()) { // Get a buffer from the cut detector output pin's allocator hr = pTextOutput->GetDeliveryBuffer(&pOutput, NULL, NULL, 0); if (FAILED(hr)) return hr; // Set sample properties pOutput->SetTime(NULL, NULL); pOutput->SetSyncPoint(FALSE); pOutput->SetDiscontinuity(TRUE); pOutput->SetPreroll(FALSE); pOutput->SetMediaTime(NULL, NULL); // Copy message to buffer hr = pOutput->GetPointer((BYTE**)&pOutData); if (FAILED(hr)) return hr; sprintf(pOutData, "%9d\t%9d\t%9g\t%9g\t%9g\t%9g\t%9g\t%9g\t%9g\n",FrameNo,f1,f2,f3,f4,I1,I2,I3,I4); //sprintf(pOutData, "%8d %14g %4d", FrameNo, Confidence, Duration); hr = pOutput->SetActualDataLength(1 + strlen(pOutData)); if (FAILED(hr)) return hr; // Deliver the output hr = pTextOutput->Deliver(pOutput); pOutput->Release(); if (FAILED(hr)) return hr; } if (Params.pCallBack != NULL) { if (Params.pCallBack(FrameNo,f1,f2,f3,f4,I1,I2,I3,I4) != 0) //if (Params.pCallBack(FrameNo,f1,f2,f3,f4,I1,I2) != 0) // Application wants to abort - what can we do if we aren't a renderer? if ((GetMiscFlags() & AM_FILTER_MISC_FLAGS_IS_RENDERER) != 0) { // Send an EC_COMPLETE event to stop the graph hr = NotifyEvent(EC_COMPLETE, 0, 0); if (FAILED(hr)) return hr; } } return hr; } VideoInPin::VideoInPin(CBaseFilter *pFilter, CCritSec *pLock, HRESULT *phr) : CBaseInputPin(NAME("cut detector input"), pFilter, pLock, phr, psudPins[VideoInputNo].strName) { } STDMETHODIMP VideoInPin::EndOfStream(void) { CAutoLock LockStream(&StreamLock); HRESULT hr; hr = ((CCutDetector*)m_pFilter)->EndOfStream(); if (FAILED(hr)) return hr; return CBaseInputPin::EndOfStream(); } STDMETHODIMP VideoInPin::BeginFlush(void) { CAutoLock LockFilter(m_pLock); HRESULT hr; // First, make sure any VideoInPin::Receive that starts from now on will terminate immediately hr = CBaseInputPin::BeginFlush(); if (FAILED(hr)) return hr; // Deliver BeginFlush to all the filter's output pins hr = ((CCutDetector*)m_pFilter)->DeliverBeginFlush(); if (FAILED(hr)) return hr; // Lock the stream here to wait for any running VideoInPin::Receive to finish CAutoLock LockStream(&StreamLock); // Release any samples we're holding ((CCutDetector*)m_pFilter)->ReleaseSamples(); return hr; } STDMETHODIMP VideoInPin::EndFlush(void) { CAutoLock LockFilter(m_pLock); HRESULT hr; hr = ((CCutDetector*)m_pFilter)->DeliverEndFlush(); if (FAILED(hr)) return hr; return CBaseInputPin::EndFlush(); } STDMETHODIMP VideoInPin::Receive(IMediaSample *pSample) { CAutoLock LockStream(&StreamLock); HRESULT hr; // Check that all is well (implemented in the base class) hr = CBaseInputPin::Receive(pSample); if (hr != S_OK) return hr; // Main filter class does all the work return ((CCutDetector*)m_pFilter)->Receive(pSample); } HRESULT VideoInPin::SetMediaType(const CMediaType *pmt) { HRESULT hr; hr = CBasePin::SetMediaType(pmt); if (FAILED(hr)) return hr; return ((CCutDetector*)m_pFilter)->SetMediaType(pmt); } HRESULT VideoInPin::CheckMediaType(const CMediaType *pmt) { if (*pmt->Type() != MEDIATYPE_Video || *pmt->Subtype() != MEDIASUBTYPE_YUY2) return VFW_E_TYPE_NOT_ACCEPTED; // is downstream filter happy with this type? if (m_pFilter->GetPin(VideoOutputNo)->IsConnected()) return m_pFilter->GetPin(VideoOutputNo)->GetConnected()->QueryAccept(pmt); return S_OK; } HRESULT VideoInPin::GetMediaType(int iPosition, CMediaType *pMediaType) { CAutoLock LockFilter(m_pLock); HRESULT hr; if (iPosition < 0) return E_INVALIDARG; if (iPosition > 0) return VFW_S_NO_MORE_ITEMS; if (m_pFilter->GetPin(VideoOutputNo)->IsConnected()) { // Can only accept connections of the same type hr = pMediaType->Set(((VideoOutPin*)m_pFilter->GetPin(VideoOutputNo))->CurrentMediaType()); if (FAILED(hr)) return hr; } else { // Specify our preferred media type pMediaType->InitMediaType(); pMediaType->SetType(&MEDIATYPE_Video); pMediaType->SetSubtype(&MEDIASUBTYPE_YUY2); } return S_OK; } HRESULT VideoInPin::CompleteConnect(IPin *pReceivePin) { HRESULT hr; if (m_pFilter->GetPin(VideoOutputNo)->IsConnected()) { // Reconnect output pin to make sure it uses the input's allocator and media type hr = m_pFilter->ReconnectPin(m_pFilter->GetPin(VideoOutputNo), &m_mt); if (FAILED(hr)) return hr; } // Pass the call on to the base class return CBaseInputPin::CompleteConnect(pReceivePin); } // NotifyAllocator is overridden as we can't trust the upstream filter to allocate an extra // buffer if we had reqested it with GetAllocatorRequirements. STDMETHODIMP VideoInPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) { CAutoLock LockFilter(m_pLock); ALLOCATOR_PROPERTIES Actual, Request; HRESULT hr; // Get allocator properties set by upstream filter hr = pAllocator->GetProperties(&Actual); if (FAILED(hr)) return hr; // Set our requirements (one extra buffer) Request = Actual; Request.cBuffers = Request.cBuffers + 1; hr = pAllocator->SetProperties(&Request, &Actual); if (FAILED(hr)) return hr; // Check that our request has been met if (Actual.cBuffers < Request.cBuffers || Actual.cbBuffer < Request.cbBuffer || Actual.cbAlign < Request.cbAlign || Actual.cbPrefix < Request.cbPrefix) return E_FAIL; // Notify the base class about the allocator return CBaseInputPin::NotifyAllocator(pAllocator, bReadOnly); } ConvertSampleTime::ConvertSampleTime() { FrameDuration = 400000; LastStartTime = 0; RefTime = 0; RefFrame = 0; FrameCount = 0; TimeOffset = 0; FDError = 0; } void ConvertSampleTime::ReStart() { LastStartTime = 0; RefTime = 0; RefFrame = 0; FrameCount = 0; TimeOffset = 0; FDError = 0; } void ConvertSampleTime::SetMediaType(const AM_MEDIA_TYPE *pmt) { if (pmt->formattype == FORMAT_VideoInfo) FrameDuration = ((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame; else if (pmt->formattype == FORMAT_VideoInfo2) FrameDuration = ((VIDEOINFOHEADER2*)pmt->pbFormat)->AvgTimePerFrame; } inline REFERENCE_TIME ConvertSampleTime::rdiv(const REFERENCE_TIME a, const REFERENCE_TIME b) { if (a > 0) return (a + (b / 2)) / b; else return (a - (b / 2)) / b; } int ConvertSampleTime::GetFrameNo(IMediaSample *pSample) { REFERENCE_TIME ThisFrameNo; REFERENCE_TIME TimeError; REFERENCE_TIME CorrDuration; REFERENCE_TIME StartTime, StopTime; if (pSample->GetMediaTime(&StartTime, &StopTime) != S_OK) if (pSample->GetTime(&StartTime, &StopTime) != S_OK) return -1; CorrDuration = FrameDuration + rdiv(FDError, TimeScale); ThisFrameNo = rdiv(StartTime - TimeOffset, CorrDuration); TimeError = (StartTime - LastStartTime) - FrameDuration; if (TimeError < -2000 || TimeError > 2000) // Major glitch in frame duration - reset reference point after more frames have arrived FrameCount = -20; if (FrameCount == 0) { RefTime = StartTime; RefFrame = ThisFrameNo; } if (FrameCount > 500) { // Have large enough time interval to compute slope TimeError = (StartTime - RefTime) - (FrameDuration * (ThisFrameNo - RefFrame)); TimeError = rdiv(TimeError * TimeScale, ThisFrameNo - RefFrame); FDError = FDError + rdiv(TimeError - FDError, 1000); // Adjust offset CorrDuration = FrameDuration + rdiv(FDError, TimeScale); TimeOffset = RefTime - (CorrDuration * RefFrame); } LastStartTime = StartTime; FrameCount = FrameCount + 1; return (int)ThisFrameNo; } QueuedOutputPin::QueuedOutputPin(TCHAR *pObjectName, CBaseFilter *pFilter, CCritSec *pLock, HRESULT *phr, LPCWSTR pName) : pOutputQueue(NULL), CBaseOutputPin(pObjectName, pFilter, pLock, phr, pName) { } HRESULT QueuedOutputPin::Active() { HRESULT hr = S_OK; // Create the output queue if (pOutputQueue == NULL) { pOutputQueue = new COutputQueue(GetConnected(), &hr, TRUE, FALSE); if (pOutputQueue == NULL) return E_OUTOFMEMORY; if (FAILED(hr)) { delete pOutputQueue; pOutputQueue = NULL; return hr; } } // Pass the call on to the base class return CBaseOutputPin::Active(); } HRESULT QueuedOutputPin::Inactive() { // Delete the output queue if (pOutputQueue != NULL) { delete pOutputQueue; pOutputQueue = NULL; } // Pass the call on to the base class return CBaseOutputPin::Inactive(); } HRESULT QueuedOutputPin::Deliver(IMediaSample *pMediaSample) { if (pOutputQueue == NULL) return S_OK; pMediaSample->AddRef(); return pOutputQueue->Receive(pMediaSample); } HRESULT QueuedOutputPin::DeliverEndOfStream() { if (pOutputQueue != NULL) pOutputQueue->EOS(); return S_OK; } HRESULT QueuedOutputPin::DeliverBeginFlush() { if (pOutputQueue != NULL) pOutputQueue->BeginFlush(); return S_OK; } HRESULT QueuedOutputPin::DeliverEndFlush() { if (pOutputQueue != NULL) pOutputQueue->EndFlush(); return S_OK; } VideoOutPin::VideoOutPin(CBaseFilter *pFilter,CCritSec *pLock, HRESULT *phr) : QueuedOutputPin(NAME("cut detector video output"), pFilter, pLock, phr, psudPins[VideoOutputNo].strName) { } // Instead of the video output pin choosing an allocator, it just uses whatever the // upstream filter has chosen. HRESULT VideoOutPin::DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc) { HRESULT hr = S_OK; // Get the allocator from the video input pin *ppAlloc = ((VideoInPin*)m_pFilter->GetPin(VideoInputNo))->PeekAllocator(); // Tell the downstream filter about the allocator set by the upstream filter, but read only. hr = pPin->NotifyAllocator(*ppAlloc,TRUE); if (FAILED(hr)) { *ppAlloc = NULL; return hr; } (*ppAlloc)->AddRef(); return S_OK; } // DecideBufferSize is pure virtual in the base class, so must be implemented. // It is never called because we've overridden DecideAllocator. HRESULT VideoOutPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) { return S_OK; } HRESULT VideoOutPin::CheckMediaType(const CMediaType *pmt) { // reject some media types straight away if (*pmt->Type() != MEDIATYPE_Video || *pmt->Subtype() != MEDIASUBTYPE_YUY2) return VFW_E_TYPE_NOT_ACCEPTED; // is upstream filter happy with this type? if (m_pFilter->GetPin(VideoInputNo)->IsConnected()) return m_pFilter->GetPin(VideoInputNo)->GetConnected()->QueryAccept(pmt); return S_OK; } HRESULT VideoOutPin::GetMediaType(int iPosition, CMediaType *pMediaType) { CAutoLock LockFilter(m_pLock); HRESULT hr; IEnumMediaTypes* pEnum; AM_MEDIA_TYPE* PartnerMT[100]; ULONG Fetched; int ValidCount; if (iPosition < 0) return E_INVALIDARG; if (m_pFilter->GetPin(VideoInputNo)->IsConnected()) { // pass on all preferred media types from upstream filter that are OK with us hr = m_pFilter->GetPin(VideoInputNo)->GetConnected()->EnumMediaTypes(&pEnum); if (FAILED(hr)) return hr; hr = pEnum->Next(sizeof(PartnerMT) / sizeof(PartnerMT[0]), PartnerMT, &Fetched); if (FAILED(hr)) return hr; pEnum->Release(); ValidCount = 0; for (ULONG i = 0; i < Fetched; i++) { if (PartnerMT[i]->majortype == MEDIATYPE_Video && PartnerMT[i]->subtype == MEDIASUBTYPE_YUY2) { if (ValidCount == iPosition) hr = pMediaType->Set(*PartnerMT[i]); ValidCount = ValidCount + 1; } DeleteMediaType(PartnerMT[i]); } if (FAILED(hr)) return hr; if (iPosition >= ValidCount) return VFW_S_NO_MORE_ITEMS; } else { // specify our preferred media type if (iPosition > 0) return VFW_S_NO_MORE_ITEMS; pMediaType->InitMediaType(); pMediaType->SetType(&MEDIATYPE_Video); pMediaType->SetSubtype(&MEDIASUBTYPE_YUY2); } return S_OK; } HRESULT VideoOutPin::CompleteConnect(IPin *pReceivePin) { HRESULT hr; if (m_pFilter->GetPin(VideoInputNo)->IsConnected() && m_mt != ((VideoInPin*)m_pFilter->GetPin(VideoInputNo))->CurrentMediaType()) { // Reconnect input pin to make it use the output's media type hr = m_pFilter->ReconnectPin(m_pFilter->GetPin(VideoInputNo), &m_mt); if (FAILED(hr)) return hr; } // Pass the call on to the base class return CBaseOutputPin::CompleteConnect(pReceivePin); } // We ignore quality control messages, as we do not want to skip frames! STDMETHODIMP VideoOutPin::Notify(IBaseFilter *pSender, Quality q) { return E_NOTIMPL; } TextOutPin::TextOutPin(CBaseFilter *pFilter,CCritSec *pLock, HRESULT *phr) : QueuedOutputPin(NAME("cut detector output"), pFilter, pLock, phr, psudPins[TextOutputNo].strName) { } HRESULT TextOutPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) { HRESULT hr; ALLOCATOR_PROPERTIES Actual; // One buffer to hold a string of up to 127 chars ppropInputRequest->cBuffers = max(ppropInputRequest->cBuffers, 1); ppropInputRequest->cbBuffer = max(ppropInputRequest->cbBuffer, 128); hr = pAlloc->SetProperties(ppropInputRequest, &Actual); if (FAILED(hr)) return hr; if (Actual.cBuffers < ppropInputRequest->cBuffers || Actual.cbBuffer < ppropInputRequest->cbBuffer || Actual.cbAlign < ppropInputRequest->cbAlign || Actual.cbPrefix < ppropInputRequest->cbPrefix) return E_FAIL; return S_OK; } HRESULT TextOutPin::CheckMediaType(const CMediaType *pmt) { if (*pmt->Type() != MEDIATYPE_Text) return VFW_E_TYPE_NOT_ACCEPTED; return S_OK; } HRESULT TextOutPin::GetMediaType(int iPosition, CMediaType *pMediaType) { if (iPosition < 0) return E_INVALIDARG; if (iPosition > 0) return VFW_S_NO_MORE_ITEMS; pMediaType->InitMediaType(); pMediaType->SetType(&MEDIATYPE_Text); pMediaType->SetSubtype(&MEDIASUBTYPE_NULL); return S_OK; } // We ignore quality control messages, as we do not want to skip frames! STDMETHODIMP TextOutPin::Notify(IBaseFilter *pSender, Quality q) { return E_NOTIMPL; } STDAPI DllRegisterServer() { return AMovieDllRegisterServer2(TRUE); } STDAPI DllUnregisterServer() { return AMovieDllRegisterServer2(FALSE); }