HELP! Text overlay on live video
- From: "Vincent" <Vincent@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Sun, 15 May 2005 20:26:01 -0700
Hi,
I really need your help to solve the problem. I want to do an application
which is for live video streaming with time frame on the video.
Followings is the function i modified from SDK sample.
BOOL BuildCaptureGraph()
{
USES_CONVERSION;
int cy, cyBorder;
HRESULT hr;
AM_MEDIA_TYPE *pmt=0;
// we have one already
if(m_sCap.bCaptureGraphBuilt)
{
DEBUGLOG(_T("Capture Graph Built"));
return TRUE;
}
// No rebuilding while we're running
if(m_sCap.bCapturing || m_sCap.bPreviewing)
{
DEBUGLOG(_T("Capturing or Previewing is running"));
return FALSE;
}
// We don't have the necessary capture filters
if(m_sCap.pVCap == NULL)
{
DEBUGLOG(_T("Capture filter is null"));
return FALSE;
}
// we already have another graph built... tear down the old one
if(m_sCap.bPreviewGraphBuilt)
TearDownGraph();
//
// We need a rendering section that will write the capture file out in
// AVI file format
//
GUID guid;
if( m_sCap.bMPEG2 )
{
guid = MEDIASUBTYPE_Mpeg2;
}
else
{
guid = MEDIASUBTYPE_Avi;
}
//
// Render the video capture and preview pins - even if the capture
// filter only has a capture pin (and no preview pin) this should
// work, because the capture graph builder will use a smart tee filter
// to provide both capture and preview. We don't have to worry. It
// will just work
// NOTE that we try to render the interleaved pin before the video
// pin, because if BOTH exist, it's a DV filter and the only way to get
// the audio is to use the interleaved pin. Using the Video pin on a
// DV filter is only useful if you don't want the audio.
IBaseFilter *pVideoEncoderFilter=NULL;
IH263Enc *pVidEncPropData=NULL;
IBaseFilter *pRTPPacketizerFilter=NULL;
IRtpPacket *pVidPackPropData=NULL;
IBaseFilter *pRTPSenderFilter=NULL;
IRtpSend *pVidSendPropData=NULL;
IBaseFilter *pVideoRTPPacketizerFilter = NULL;
IBaseFilter *pVideoRTPSenderFilter = NULL;
AM_MEDIA_TYPE H263pmt;
bool bHasVideo = true;
IPin *pVideoPacketizerInPin = NULL;
IPin *pVideoPacketizerOutPin = NULL;
IPin *pVideoSenderInPin = NULL;
PIN_INFO PinInfo;
IBaseFilter *pGrabberF = NULL;
ISampleGrabber *pGrabber;
if (m_bTextOverlay)
{
hr = S_OK;
hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pGrabberF);
if (FAILED(hr))
{
// Return an error.
}
hr = m_sCap.pFg->AddFilter(pGrabberF, L"Sample Grabber 1");
if (FAILED(hr))
{
// Return an error.
return hr;
}
pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
AM_MEDIA_TYPE mt;
CMediaType cm;
cm.SetType(&MEDIATYPE_Video);
cm.SetSubtype(&GUID_NULL );
cm.SetFormatType(&FORMAT_VideoInfo);
hr = pGrabber->SetMediaType(&cm);
}
hr = CoCreateInstance(CLSID_H263Filter, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pVideoEncoderFilter);
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to init h.263 encoder"));
return hr;
}
DEBUGLOG(_T("Init h.263 encoder"));
hr = m_sCap.pFg->AddFilter(pVideoEncoderFilter, L"Video Encoder");
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to add h.263 encoder"));
return hr;
}
DEBUGLOG(_T("Added h.263 encoder"));
hr = CoCreateInstance (CLSID_RtpPacketFilter, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pRTPPacketizerFilter);
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to init RTP packetizer filter"));
return hr;
}
DEBUGLOG(_T("init RTP packetizer filter"));
hr = m_sCap.pFg->AddFilter(pRTPPacketizerFilter, L"RTP Packetizer");
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to add RTP Packetizer"));
return hr;
}
DEBUGLOG(_T("add RTP Packetizer"));
pRTPPacketizerFilter->Release();
pRTPPacketizerFilter = NULL;
hr = CoCreateInstance (CLSID_RtpSenderFilter, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void**)&pRTPSenderFilter);
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to init RTP Sender"));
return hr;
}
DEBUGLOG(_T("init RTP Sender"));
hr = m_sCap.pFg->AddFilter(pRTPSenderFilter, L"RTP Sender");
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to add RTP Sender"));
return hr;
}
DEBUGLOG(_T("Add RTP Sender"));
pRTPSenderFilter->Release();
pRTPSenderFilter = NULL;
IEnumPins *pEnumPin = NULL;
IPin *pPinA = NULL;
IPin *pPinC = NULL;
hr = m_sCap.pVCap->EnumPins(&pEnumPin);
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to enum video capture pin"));
return FALSE
}
while (pEnumPin->Next(1, &pPinA, NULL) == S_OK)
{
hr = pPinA->QueryPinInfo(&PinInfo);
CString str(PinInfo.achName);
TRACE(_T("%s\n"), str);
if (hr == S_OK)
{
if (strcmp(PinInfo.achName, "Capture") == 0)
{
hr = pPinA->ConnectedTo(&pPinC);
if (PinInfo.dir == PINDIR_OUTPUT && hr == VFW_E_NOT_CONNECTED)
{
hr = m_sCap.pFg->Render(pPinA);
pEnumPin->Release();
hr = m_sCap.pVCap->EnumPins(&pEnumPin);
if (FAILED(hr))
{
DEBUGLOG(_T("Failed to enum video capture pin in the loop"));
return FALSE
}
}
PinInfo.pFilter->Release();
pPinA->Release();
if (pPinC)
pPinC->Release();
}
}
}
pEnumPin->Release();
TRACE(_T("Enumerating Filters...............................\n"));
EnumFilters(m_sCap.pFg);
IPin *pVideoOutPin = GetPin(pVideoEncoderFilter, PINDIR_OUTPUT);
if (!pVideoOutPin)
{
DEBUGLOG(_T("Failed to get pin for video out"));
return hr;
}
hr = pVideoOutPin->ConnectionMediaType(&H263pmt);
if (VFW_E_NOT_CONNECTED == hr)
{
bHasVideo = false;
//Error
DEBUGLOG(_T("VFW E Not connected"));
return hr;
}
else if (FAILED(hr))
{
DEBUGLOG(_T("Failed to get connection media type"));
return hr;
}
else
{
//Settings
hr = pVideoEncoderFilter->Release();
pVideoEncoderFilter = NULL;
hr = pVideoOutPin->Release();
pVideoOutPin = NULL;
}
if (bHasVideo)
{
hr = pVidEncPropData->Release();
pVidEncPropData = NULL;
hr = pVidPackPropData->Release();
pVidPackPropData = NULL;
hr = pVidSendPropData->Release();
pVidSendPropData = NULL;
}
if( !m_sCap.bMPEG2 )
{
if(m_sCap.bWantPreview)
{
hr = m_sCap.pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Interleaved,
m_sCap.pVCap, NULL, NULL);
if(hr == VFW_S_NOPREVIEWPIN)
{
// preview was faked up for us using the (only) capture pin
m_sCap.bPreviewFaked = TRUE;
}
else if(hr != S_OK)
{
hr = m_sCap.pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
m_sCap.pVCap, NULL, NULL);
if(hr == VFW_S_NOPREVIEWPIN)
{
// preview was faked up for us using the (only) capture
pin
m_sCap.bPreviewFaked = TRUE;
}
else if(hr != S_OK)
{
ErrMsg(_T("Cannot render video preview stream
[BuildCaptureGraph]"));
DEBUGLOG(_T("Setup Capture failed"));
TearDownGraph();
return FALSE;
}
}
}
}
else
{
CComPtr< IBaseFilter > sink;
if( &m_sCap.pSink )
{
m_sCap.pSink->QueryInterface( IID_IBaseFilter,
reinterpret_cast<void **>( &sink ) );
}
hr = m_sCap.pBuilder->RenderStream(NULL,
&MEDIATYPE_Stream,
m_sCap.pVCap, NULL, sink);
}
if (m_bTextOverlay)
{
hr = pGrabber->GetConnectedMediaType( &g_StillMediaType );
VIDEOINFO* pVI = (VIDEOINFO*) g_StillMediaType.pbFormat;
pGrabber->SetBufferSamples(FALSE);
pGrabber->SetOneShot(FALSE);
pGrabber->SetCallback(&g_StillCapCB, 0);
}
//
// Get the preview window to be a child of our app's window
//
// This will find the IVideoWindow interface on the renderer. It is
// important to ask the filtergraph for this interface... do NOT use
// ICaptureGraphBuilder2::FindInterface, because the filtergraph needs to
// know we own the window so it can give us display changed messages, etc.
if(!m_sCap.bMPEG2 && m_sCap.bWantPreview)
{
hr = m_sCap.pFg->QueryInterface(IID_IVideoWindow, (void
**)&m_sCap.pVW);
if(hr != NOERROR && m_sCap.bWantPreview)
{
ErrMsg(_T("This graph cannot preview [BuildCaptureGraph]"));
}
else if(hr == NOERROR)
{
RECT rc;
m_sCap.pVW->put_Owner((OAHWND)m_hWnd); // We own the window now
m_sCap.pVW->put_WindowStyle(WS_CHILD); // you are now a child
// give the preview window all our space but where the status
bar is
GetClientRect(&rc);
cyBorder = GetSystemMetrics(SM_CYBORDER);
cy = StatusGetHeight() + cyBorder;
rc.bottom -= cy;
m_sCap.pVW->SetWindowPosition(0, 0, rc.right, rc.bottom); // be
this big
m_sCap.pVW->put_Visible(OATRUE);
}
}
// now ask the filtergraph to tell us when something is completed or
aborted
// (EC_COMPLETE, EC_USERABORT, EC_ERRORABORT). This is how we will find
out
// if the disk gets full while capturing
hr = m_sCap.pFg->QueryInterface(IID_IMediaEventEx, (void **)&m_sCap.pME);
if(hr == NOERROR)
{
m_sCap.pME->SetNotifyWindow((OAHWND)m_hWnd, WM_FGNOTIFY, 0);
}
// potential debug output - what the graph looks like
// DumpGraph(gcap.pFg, 1);
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
#ifdef REGISTER_FILTERGRAPH
hr = AddGraphToRot(m_sCap.pFg, &g_dwGraphRegister);
if(FAILED(hr))
{
ErrMsg(_T("Failed to register filter graph with ROT
[BuildCaptureGraph] hr=0x%x"), hr);
g_dwGraphRegister = 0;
}
#endif
// All done.
m_sCap.bCaptureGraphBuilt = TRUE;
return TRUE;
}
What I get in the GraphEdit is :
Capture ---> SampleGrabber->Color Space Converter->Video Renderer
Preview --> AVI Decompressor -> Video Renderer 001
and Unconnected filters:
Color Space Converter->Video Encoder->RTP Packetizer->RTP Sender
My concern is how to make the Sample Grabber connect to Video Encoder???
Any error in the code? Please help me to point out the error.
All helps are appreciate! Thanks
.
- Follow-Ups:
- Re: HELP! Text overlay on live video
- From: Tim Roberts
- Re: HELP! Text overlay on live video
- Prev by Date: DES graph using multiple video source formats
- Next by Date: Re: DES graph using multiple video source formats
- Previous by thread: DES graph using multiple video source formats
- Next by thread: Re: HELP! Text overlay on live video
- Index(es):
Relevant Pages
|