HRESULT CCcFilter::ReadFromStream(IStream *pStream) { int iChannel = 0; AM_LINE21_CCSERVICE iService = AM_L21_CCSERVICE_Caption1; ICcParser_CCTYPE iXformType = ICcParser_CCTYPE_ATSC_A53; if( mPS_dwFileVersion = iCurrentMajorVersion ) { HRESULT hr; int iData = ReadInt(pStream, hr); if( SUCCEEDED(hr)) { int iDataInts = iData; if( iDataInts > 0 ) { iData = ReadInt(pStream, hr); if( SUCCEEDED(hr)) iChannel = iData; iDataInts--; } if( iDataInts > 0 ) { iData = ReadInt(pStream, hr); if( SUCCEEDED(hr)) iService = (AM_LINE21_CCSERVICE)iData; iDataInts--; } if( iDataInts > 0 ) { iData = ReadInt(pStream, hr); if( SUCCEEDED(hr)) iXformType = (ICcParser_CCTYPE)iData; iDataInts--; } } } VERIFY( SUCCEEDED( put_Channel( iChannel ))); VERIFY( SUCCEEDED( put_Service( iService ))); VERIFY( SUCCEEDED( put_XformType( iXformType ))); CPersistStream::SetDirty( FALSE ); return NOERROR; }
bool directx_camera_server::open_moniker_and_finish_setup( comutils::Ptr<IMoniker> pMoniker, FilterOperation const &sourceConfig, unsigned width, unsigned height) { if (!pMoniker) { fprintf(stderr, "directx_camera_server::open_moniker_and_finish_setup(): " "Null device moniker passed: no device found?\n"); return false; } auto prop = PropertyBagHelper{*pMoniker}; printf("directx_camera_server: Using capture device '%s' at path '%s'\n", getDeviceHumanDesc(prop).c_str(), getDevicePath(prop).c_str()); // Bind the chosen moniker to a filter object. auto pSrc = comutils::Ptr<IBaseFilter>{}; pMoniker->BindToObject(nullptr, nullptr, IID_IBaseFilter, AttachPtr(pSrc)); //------------------------------------------------------------------- // Construct the sample grabber that will be used to snatch images from // the video stream as they go by. Set its media type and callback. // Create and configure the Sample Grabber. _pSampleGrabberWrapper.reset(new SampleGrabberWrapper); // Get the exchange object for receiving data from the sample grabber. sampleExchange_ = _pSampleGrabberWrapper->getExchange(); //------------------------------------------------------------------- // Ask for the video resolution that has been passed in. // This code is based on // intuiting that we need to use the SetFormat call on the IAMStreamConfig // interface; this interface is described in the help pages. // If the width and height are specified as 0, then they are not set // in the header, letting them use whatever is the default. /// @todo factor this out into its own header. if ((width != 0) && (height != 0)) { auto pStreamConfig = comutils::Ptr<IAMStreamConfig>{}; _pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSrc.get(), IID_IAMStreamConfig, AttachPtr(pStreamConfig)); checkForConstructionError(pStreamConfig, "StreamConfig interface"); AM_MEDIA_TYPE mt = {0}; mt.majortype = MEDIATYPE_Video; // Ask for video media producers mt.subtype = MEDIASUBTYPE_RGB24; // Ask for 8 bit RGB VIDEOINFOHEADER vih = {0}; mt.pbFormat = reinterpret_cast<BYTE *>(&vih); auto pVideoHeader = &vih; pVideoHeader->bmiHeader.biBitCount = 24; pVideoHeader->bmiHeader.biWidth = width; pVideoHeader->bmiHeader.biHeight = height; pVideoHeader->bmiHeader.biPlanes = 1; pVideoHeader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pVideoHeader->bmiHeader.biSizeImage = dibsize(pVideoHeader->bmiHeader); // Set the format type and size. mt.formattype = FORMAT_VideoInfo; mt.cbFormat = sizeof(VIDEOINFOHEADER); // Set the sample size. mt.bFixedSizeSamples = TRUE; mt.lSampleSize = dibsize(pVideoHeader->bmiHeader); // Make the call to actually set the video type to what we want. if (pStreamConfig->SetFormat(&mt) != S_OK) { fprintf(stderr, "directx_camera_server::open_and_find_parameters():" " Can't set resolution to %dx%d using uncompressed " "24-bit video\n", pVideoHeader->bmiHeader.biWidth, pVideoHeader->bmiHeader.biHeight); return false; } } //------------------------------------------------------------------- // Create a null renderer that will be used to discard the video frames // on the output pin of the sample grabber #ifdef DEBUG printf("directx_camera_server::open_and_find_parameters(): Before " "createNullRenderFilter\n"); #endif auto pNullRender = createNullRenderFilter(); auto sampleGrabberFilter = _pSampleGrabberWrapper->getFilter(); //------------------------------------------------------------------- // Build the filter graph. First add the filters and then connect them. // pSrc is the capture filter for the video device we found above. auto hr = _pGraph->AddFilter(pSrc.get(), L"Video Capture"); BOOST_ASSERT_MSG(SUCCEEDED(hr), "Adding Video Capture filter to graph"); // Add the sample grabber filter hr = _pGraph->AddFilter(sampleGrabberFilter.get(), L"SampleGrabber"); BOOST_ASSERT_MSG(SUCCEEDED(hr), "Adding SampleGrabber filter to graph"); // Add the null renderer filter hr = _pGraph->AddFilter(pNullRender.get(), L"NullRenderer"); BOOST_ASSERT_MSG(SUCCEEDED(hr), "Adding NullRenderer filter to graph"); // Connect the output of the video reader to the sample grabber input ConnectTwoFilters(*_pGraph, *pSrc, *sampleGrabberFilter); // Connect the output of the sample grabber to the null renderer input ConnectTwoFilters(*_pGraph, *sampleGrabberFilter, *pNullRender); // If we were given a config action for the source, do it now. if (sourceConfig) { sourceConfig(*pSrc); } //------------------------------------------------------------------- // XXX See if this is a video tuner card by querying for that interface. // Set it to read the video channel if it is one. auto pTuner = comutils::Ptr<IAMTVTuner>{}; hr = _pBuilder->FindInterface(nullptr, nullptr, pSrc.get(), IID_IAMTVTuner, AttachPtr(pTuner)); if (pTuner) { #ifdef DEBUG printf("directx_camera_server::open_and_find_parameters(): Found a TV " "Tuner!\n"); #endif // XXX Put code here. // Set the first input pin to use the cable as input hr = pTuner->put_InputType(0, TunerInputCable); if (FAILED(hr)) { fprintf(stderr, "directx_camera_server::open_and_find_parameters():" " Can't set input to cable\n"); } // Set the channel on the video to be baseband (is this channel zero?) hr = pTuner->put_Channel(0, -1, -1); if (FAILED(hr)) { fprintf(stderr, "directx_camera_server::open_and_find_parameters():" " Can't set channel\n"); } } //------------------------------------------------------------------- // Find _num_rows and _num_columns in the video stream. AM_MEDIA_TYPE mt = {0}; _pSampleGrabberWrapper->getConnectedMediaType(mt); VIDEOINFOHEADER *pVih; if (mt.formattype == FORMAT_VideoInfo || mt.formattype == FORMAT_VideoInfo2) { pVih = reinterpret_cast<VIDEOINFOHEADER *>(mt.pbFormat); } else { fprintf(stderr, "directx_camera_server::open_and_find_parameters(): " "Can't get video header type\n"); fprintf(stderr, " (Expected %x or %x, got %x)\n", FORMAT_VideoInfo, FORMAT_VideoInfo2, mt.formattype); fprintf(stderr, " (GetConnectedMediaType is not valid for DirectX " "headers later than version 7)\n"); fprintf(stderr, " (We need to re-implement reading video in some " "other interface)\n"); return false; } // Number of rows and columns. This is different if we are using a target // rectangle (rcTarget) than if we are not. if (IsRectEmpty(&pVih->rcTarget)) { _num_columns = pVih->bmiHeader.biWidth; _num_rows = pVih->bmiHeader.biHeight; } else { _num_columns = pVih->rcTarget.right; _num_rows = pVih->bmiHeader.biHeight; printf("XXX directx_camera_server::open_and_find_parameters(): " "Warning: may not work correctly with target rectangle\n"); } #ifdef DEBUG printf("Got %dx%d video\n", _num_columns, _num_rows); #endif // Make sure that the image is not compressed and that we have 8 bits // per pixel. if (pVih->bmiHeader.biCompression != BI_RGB) { fprintf(stderr, "directx_camera_server::open_and_find_parameters(): " "Compression not RGB\n"); switch (pVih->bmiHeader.biCompression) { case BI_RLE8: fprintf(stderr, " (It is BI_RLE8)\n"); break; case BI_RLE4: fprintf(stderr, " (It is BI_RLE4)\n"); case BI_BITFIELDS: fprintf(stderr, " (It is BI_BITFIELDS)\n"); break; default: fprintf(stderr, " (Unknown compression type)\n"); } return false; } int BytesPerPixel = pVih->bmiHeader.biBitCount / 8; if (BytesPerPixel != 3) { fprintf(stderr, "directx_camera_server::open_and_find_parameters(): " "Not 3 bytes per pixel (%d)\n", pVih->bmiHeader.biBitCount); return false; } // A negative height indicates that the images are stored non-inverted in Y // Not sure what to do with images that have negative height -- need to // read the book some more to find out. if (_num_rows < 0) { fprintf(stderr, "directx_camera_server::open_and_find_parameters(): " "Num Rows is negative (internal error)\n"); return false; } // Find the stride to take when moving from one row of video to the // next. This is rounded up to the nearest DWORD. _stride = (_num_columns * BytesPerPixel + 3) & ~3; return true; }