/* * Class: sage_DShowMediaPlayer * Method: setGraphVolume0 * Signature: (JF)F */ JNIEXPORT jfloat JNICALL Java_sage_DShowMediaPlayer_setGraphVolume0 (JNIEnv *env, jobject jo, jlong dataPtr, jfloat vol) { if (!dataPtr) return 0; CPlayerData* playData = (CPlayerData*) dataPtr; IGraphBuilder* pGraph = playData->GetGraph(); vol = MAX(0, MIN(1.0f, vol)); if (pGraph) { IBasicAudio *pAudio = NULL; HRESULT hr = pGraph->QueryInterface(IID_IBasicAudio, (void**)&pAudio); if (SUCCEEDED(hr)) { long theVolume; if (vol == 0) theVolume = -10000; else { theVolume = (long)(10000*log((vol*2999.0) + 1)/log(3000.0)) - 10000; } hr = pAudio->put_Volume(theVolume); SAFE_RELEASE(pAudio); } } return vol; }
void DeviceSource::Preprocess() { if(!bCapturing) return; //---------------------------------------- if(bRequestVolume) { if(audioOut) audioOut->SetVolume(fNewVol); else if(audioFilter) { IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(fNewVol)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } bRequestVolume = false; } //---------------------------------------- SampleData *lastSample = NULL; OSEnterMutex(hSampleMutex); lastSample = latestVideoSample; latestVideoSample = NULL; OSLeaveMutex(hSampleMutex); //---------------------------------------- int numThreads = MAX(OSGetTotalCores()-2, 1); if(lastSample) { /*REFERENCE_TIME refTimeStart, refTimeFinish; lastSample->GetTime(&refTimeStart, &refTimeFinish); static REFERENCE_TIME lastRefTime = 0; //Log(TEXT("refTimeStart: %llu, refTimeFinish: %llu, offset = %llu"), refTimeStart, refTimeFinish, refTimeStart-lastRefTime); lastRefTime = refTimeStart;*/ lastSample->Release(); } }
void PlaybackControls::setVolume(int volume) { IBasicAudio *pBasicAudio; mVolume = volume; if (mpGraph) { HRESULT hr = mpGraph->QueryInterface(IID_IBasicAudio, (void **)&pBasicAudio); if (SUCCEEDED(hr)) { if (volume == -10000) volume = -25000; pBasicAudio->put_Volume(volume/2.5); } pBasicAudio->Release(); } }
void DeviceSource::GlobalSourceLeaveScene() { if(soundOutputType == 1) { audioOut->SetVolume(0.0f); } if(soundOutputType == 2) { IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(0.0)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } }
void DeviceSource::GlobalSourceEnterScene() { float sourceVolume = data->GetFloat(TEXT("volume"), 1.0f); if(soundOutputType == 1) { audioOut->SetVolume(sourceVolume); } if(soundOutputType == 2) { IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(sourceVolume)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } }
const bool CMediaViewer::SetVolume(const float fVolume) { // オーディオボリュームをdBで設定する( -100.0(無音) < fVolume < 0(最大) ) IBasicAudio *pBasicAudio; bool fOK=false; if (m_pFilterGraph) { if (SUCCEEDED(m_pFilterGraph->QueryInterface( IID_IBasicAudio, pointer_cast<void**>(&pBasicAudio)))) { long lVolume = (long)(fVolume * 100.0f); if (lVolume>=-10000 && lVolume<=0) { TRACE(TEXT("Volume Control = %d\n"),lVolume); if (SUCCEEDED(pBasicAudio->put_Volume(lVolume))) fOK=true; } pBasicAudio->Release(); } } return fOK; }
/* * Class: sage_DShowMediaPlayer * Method: getGraphVolume0 * Signature: (J)F */ JNIEXPORT jfloat JNICALL Java_sage_DShowMediaPlayer_getGraphVolume0 (JNIEnv *env, jobject jo, jlong dataPtr) { if (!dataPtr) return 0; CPlayerData* playData = (CPlayerData*) dataPtr; IGraphBuilder* pGraph = playData->GetGraph(); if (pGraph) { IBasicAudio *pAudio = NULL; HRESULT hr = pGraph->QueryInterface(IID_IBasicAudio, (void**)&pAudio); if (SUCCEEDED(hr)) { long theVolume; hr = pAudio->get_Volume(&theVolume); SAFE_RELEASE(pAudio); if (SUCCEEDED(hr)) { // the volume ranges from -10,000 to 0 return (theVolume/10000.0f) + 1; } } } return 0; }
STDMETHODIMP CWaveOutRenderer::NonDelegatingQueryInterface(REFIID riid, void** o) { if (!o) return E_POINTER; *o = NULL; if (IID_IDispatch == riid) { IDispatch* d = this; d->AddRef(); *o = d; return S_OK; } if (IID_IBasicAudio == riid) { IBasicAudio* b = this; b->AddRef(); *o = b; return S_OK; } return CBaseRenderer::NonDelegatingQueryInterface (riid, o); }
bool DeviceSource::LoadFilters() { if(bCapturing || bFiltersLoaded) return false; bool bSucceeded = false; List<MediaOutputInfo> outputList; IAMStreamConfig *config = NULL; bool bAddedVideoCapture = false, bAddedAudioCapture = false, bAddedDevice = false; GUID expectedMediaType; IPin *devicePin = NULL, *audioPin = NULL; HRESULT err; String strShader; bUseThreadedConversion = API->UseMultithreadedOptimizations() && (OSGetTotalCores() > 1); //------------------------------------------------ // basic initialization vars bool bCheckForceAudio = data->GetInt(TEXT("forceCustomAudioDevice")) != 0; bUseCustomResolution = data->GetInt(TEXT("customResolution")); strDevice = data->GetString(TEXT("device")); strDeviceName = data->GetString(TEXT("deviceName")); strDeviceID = data->GetString(TEXT("deviceID")); strAudioDevice = data->GetString(TEXT("audioDevice")); strAudioName = data->GetString(TEXT("audioDeviceName")); strAudioID = data->GetString(TEXT("audioDeviceID")); strAudioGUID = data->GetString(TEXT("audioDeviceCLSID")); if(strAudioGUID.Compare(TEXT("CLSID_AudioInputDeviceCategory"))) matchGUID = CLSID_AudioInputDeviceCategory; if(strAudioGUID.Compare(TEXT("CLSID_VideoInputDeviceCategory"))) matchGUID = CLSID_VideoInputDeviceCategory; if(strAudioGUID.Compare(TEXT("CLSID_AudioRendererCategory"))) { //Log(TEXT("Dese are spekers.\n")); matchGUID = CLSID_AudioRendererCategory; } bFlipVertical = data->GetInt(TEXT("flipImage")) != 0; bFlipHorizontal = data->GetInt(TEXT("flipImageHorizontal")) != 0; opacity = data->GetInt(TEXT("opacity"), 100); float volume = data->GetFloat(TEXT("volume"), 1.0f); //------------------------------------------------ // chrom key stuff bUseChromaKey = data->GetInt(TEXT("useChromaKey")) != 0; keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF); keySimilarity = data->GetInt(TEXT("keySimilarity")); keyBlend = data->GetInt(TEXT("keyBlend"), 80); keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50); if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z) keyBaseColor -= keyBaseColor.x; else if(keyBaseColor.y < keyBaseColor.x && keyBaseColor.y < keyBaseColor.z) keyBaseColor -= keyBaseColor.y; else if(keyBaseColor.z < keyBaseColor.x && keyBaseColor.z < keyBaseColor.y) keyBaseColor -= keyBaseColor.z; //------------------------------------------------ // get the device filter and pins if(strAudioDevice.IsValid()) { audioDeviceFilter = GetDeviceByValue(matchGUID, L"FriendlyName", strAudioName, L"DevicePath", strAudioID); if(!audioDeviceFilter) { AppWarning(TEXT("DShowAudioPlugin: Invalid audio device: name '%s', path '%s'"), strAudioName.Array(), strAudioID.Array()); } } soundOutputType = data->GetInt(TEXT("soundOutputType")); if(soundOutputType != 0) { if(matchGUID == CLSID_AudioRendererCategory) { err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); } else { err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); } if(FAILED(err)) { Log(TEXT("DShowAudioPlugin: No audio pin, result = %lX"), err); soundOutputType = 0; } } int soundTimeOffset = data->GetInt(TEXT("soundTimeOffset")); //GetOutputList(devicePin, outputList); //------------------------------------------------ // initialize the basic video variables and data //------------------------------------------------ // log audio info { String strTest; strTest = FormattedString(TEXT(" audio device: %s,\r\n audio device id %s,\r\n"), strAudioDevice.Array(), strAudioID.Array()); Log(TEXT("------------------------------------------")); Log(strTest.Array()); } //------------------------------------------------ // get audio pin configuration, optionally configure audio pin to 44100 GUID expectedAudioType; if(soundOutputType == 1) { IAMStreamConfig *audioConfig; if(SUCCEEDED(audioPin->QueryInterface(IID_IAMStreamConfig, (void**)&audioConfig))) { AM_MEDIA_TYPE *audioMediaType; if(SUCCEEDED(err = audioConfig->GetFormat(&audioMediaType))) { SetAudioInfo(audioMediaType, expectedAudioType); //Log(TEXT("Fixed size samples: %s\r\n"), (audioMediaType->bFixedSizeSamples) ? "Yes" : "No"); //Log(TEXT("Temporal Compression: %s\r\n"), (audioMediaType->bTemporalCompression) ? "Yes" : "No"); //Log(TEXT("cbFormat: %.16X\r\n"), audioMediaType->cbFormat); //Log(TEXT("Sample size: %u\r\n"), audioMediaType->lSampleSize); } else if(err == E_NOTIMPL) //elgato probably { IEnumMediaTypes *audioMediaTypes; if(SUCCEEDED(err = audioPin->EnumMediaTypes(&audioMediaTypes))) { ULONG i = 0; if((err = audioMediaTypes->Next(1, &audioMediaType, &i)) == S_OK) SetAudioInfo(audioMediaType, expectedAudioType); else { AppWarning(TEXT("DShowAudioPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } audioMediaTypes->Release(); } else { AppWarning(TEXT("DShowAudioPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } } else { AppWarning(TEXT("DShowAudioPlugin: Could not get audio format, result = %08lX"), err); soundOutputType = 0; } audioConfig->Release(); } else { soundOutputType = 0; } } //------------------------------------------------ // add video capture filter if any captureFilter = new CaptureFilter(this, MEDIATYPE_Video, expectedMediaType); if(FAILED(err = graph->AddFilter(captureFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add video capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedVideoCapture = true; //------------------------------------------------ // add audio capture filter if any if(soundOutputType == 1) { audioFilter = new CaptureFilter(this, MEDIATYPE_Audio, expectedAudioType); if(!audioFilter) { AppWarning(TEXT("Failed to create audio capture filter")); soundOutputType = 0; } } else if(soundOutputType == 2) { if(FAILED(err = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&audioFilter))) { AppWarning(TEXT("DShowPlugin: failed to create audio renderer, result = %08lX"), err); soundOutputType = 0; } IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(volume)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } if(soundOutputType != 0) { if(FAILED(err = graph->AddFilter(audioFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add audio capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedAudioCapture = true; } //------------------------------------------------ // add primary device filter if(FAILED(err = graph->AddFilter(audioDeviceFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add audio device filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedDevice = true; //------------------------------------------------ // connect all pins and set up the whole capture thing bool bConnected; if(soundOutputType != 0) { bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, audioDeviceFilter, NULL, audioFilter)); if(!bConnected) { AppWarning(TEXT("DShowAudioPlugin: Failed to connect the audio device pin to the audio capture pin, result = %08lX"), err); soundOutputType = 0; } } if(FAILED(err = graph->QueryInterface(IID_IMediaControl, (void**)&control))) { AppWarning(TEXT("DShowAudioPlugin: Failed to get IMediaControl, result = %08lX"), err); goto cleanFinish; } if(soundOutputType == 1) { audioOut = new DeviceAudioSource; audioOut->Initialize(this); API->AddAudioSource(audioOut); audioOut->SetAudioOffset(soundTimeOffset); audioOut->SetVolume(volume); } bSucceeded = true; cleanFinish: SafeRelease(config); SafeRelease(devicePin); SafeRelease(audioPin); for(UINT i=0; i<outputList.Num(); i++) outputList[i].FreeData(); if(!bSucceeded) { bCapturing = false; if(bAddedVideoCapture) graph->RemoveFilter(captureFilter); if(bAddedAudioCapture) graph->RemoveFilter(audioFilter); if(bAddedDevice) { graph->RemoveFilter(audioDeviceFilter); graph->RemoveFilter(deviceFilter); } SafeRelease(audioDeviceFilter); SafeRelease(deviceFilter); SafeRelease(captureFilter); SafeRelease(audioFilter); SafeRelease(control); if(colorConvertShader) { delete colorConvertShader; colorConvertShader = NULL; } if(audioOut) { delete audioOut; audioOut = NULL; } if(lpImageBuffer) { Free(lpImageBuffer); lpImageBuffer = NULL; } bReadyToDraw = true; } else bReadyToDraw = false; if(!renderCX) renderCX = 32; if(!renderCY) renderCY = 32; //----------------------------------------------------- // create the texture regardless, will just show up as red to indicate failure BYTE *textureData = (BYTE*)Allocate(renderCX*renderCY*4); if(colorType == DeviceOutputType_RGB) //you may be confused, but when directshow outputs RGB, it's actually outputting BGR { msetd(textureData, 0xFFFF0000, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE); } else //if we're working with planar YUV, we can just use regular RGB textures instead { msetd(textureData, 0xFF0000FF, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE); } if(bSucceeded && bUseThreadedConversion) { if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12) { LPBYTE lpData; if(texture->Map(lpData, texturePitch)) texture->Unmap(); else texturePitch = renderCX*4; lpImageBuffer = (LPBYTE)Allocate(texturePitch*renderCY); } } Free(textureData); bFiltersLoaded = bSucceeded; return bSucceeded; }
int JukeboxDS::player() { if( FAILED(CoInitialize(NULL)) ) return -1; IGraphBuilder * pGB = NULL; IMediaControl * pMC = NULL; IBasicAudio * pBA = NULL; IMediaEvent * pME = NULL; while( m_Active ) { // check the state of the music, if stopped move onto the next file if ( pME != NULL ) { long eventCode; if ( pME->WaitForCompletion( 0, &eventCode ) == S_OK ) nextTrack(); // current song has ended, next track } // check for a volume change if ( m_UpdateVolume.signaled() ) { m_UpdateVolume.clear(); if ( pBA != NULL ) { // set the volume long pv = (100 - m_Volume) * -100; pBA->put_Volume( pv ); } } if (! m_TrackEvent.wait( 250 ) ) { AutoLock lock( &m_Lock ); if ( m_PlayLists.isValid( m_ActiveList ) && m_PlayLists[ m_ActiveList ].files.isValid( m_CurrentTrack ) ) { // get the filename of the current track CharString file = m_PlayLists[ m_ActiveList ].files[ m_CurrentTrack ]; // release the previous interfaces RELEASEQI( pGB ); RELEASEQI( pMC ); RELEASEQI( pBA ); RELEASEQI( pME ); // Create DirectShow Graph if ( FAILED( CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGB) ) ) return -1; try { // load the first file if ( FAILED( pGB->RenderFile( String( file ), NULL ) ) ) return -1; } catch( ... ) { // driver failure, don't crash the game due to a bad codec.. return -1; } // Get the IMediaControl Interface if ( FAILED( pGB->QueryInterface(IID_IMediaControl, (void **)&pMC ) ) ) return -1; // Get the IBasicAudio interface if ( FAILED( pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA) ) ) return -1; // Get the IBasicAudio interface if ( FAILED( pGB->QueryInterface(IID_IMediaEvent, (void **)&pME) ) ) return -1; // set the volume long pv = (100 - m_Volume) * -100; pBA->put_Volume( pv ); // play the music pMC->Run(); } } } RELEASEQI( pGB ); RELEASEQI( pMC ); RELEASEQI( pBA ); RELEASEQI( pME ); CoUninitialize(); return 0; }
bool DeviceSource::LoadFilters() { if(bCapturing || bFiltersLoaded) return false; bool bSucceeded = false; List<MediaOutputInfo> outputList; IAMStreamConfig *config = NULL; bool bAddedVideoCapture = false, bAddedAudioCapture = false, bAddedDevice = false; GUID expectedMediaType; IPin *devicePin = NULL, *audioPin = NULL; HRESULT err; String strShader; bUseThreadedConversion = API->UseMultithreadedOptimizations() && (OSGetTotalCores() > 1); //------------------------------------------------ // basic initialization vars bool bForceCustomAudio = data->GetInt(TEXT("forceCustomAudioDevice")) != 0; bUseCustomResolution = data->GetInt(TEXT("customResolution")); strDevice = data->GetString(TEXT("device")); strDeviceName = data->GetString(TEXT("deviceName")); strDeviceID = data->GetString(TEXT("deviceID")); strAudioDevice = data->GetString(TEXT("audioDevice")); strAudioName = data->GetString(TEXT("audioDeviceName")); strAudioID = data->GetString(TEXT("audioDeviceID")); bFlipVertical = data->GetInt(TEXT("flipImage")) != 0; bFlipHorizontal = data->GetInt(TEXT("flipImageHorizontal")) != 0; bUsePointFiltering = data->GetInt(TEXT("usePointFiltering")) != 0; opacity = data->GetInt(TEXT("opacity"), 100); float volume = data->GetFloat(TEXT("volume"), 1.0f); bUseBuffering = data->GetInt(TEXT("useBuffering")) != 0; bufferTime = data->GetInt(TEXT("bufferTime"))*10000; //------------------------------------------------ // chrom key stuff bUseChromaKey = data->GetInt(TEXT("useChromaKey")) != 0; keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF); keySimilarity = data->GetInt(TEXT("keySimilarity")); keyBlend = data->GetInt(TEXT("keyBlend"), 80); keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50); if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z) keyBaseColor -= keyBaseColor.x; else if(keyBaseColor.y < keyBaseColor.x && keyBaseColor.y < keyBaseColor.z) keyBaseColor -= keyBaseColor.y; else if(keyBaseColor.z < keyBaseColor.x && keyBaseColor.z < keyBaseColor.y) keyBaseColor -= keyBaseColor.z; //------------------------------------------------ // get the device filter and pins if(strDeviceName.IsValid()) deviceFilter = GetDeviceByValue(CLSID_VideoInputDeviceCategory, L"FriendlyName", strDeviceName, L"DevicePath", strDeviceID); else { if(!strDevice.IsValid()) { AppWarning(TEXT("DShowPlugin: Invalid device specified")); goto cleanFinish; } deviceFilter = GetDeviceByValue(CLSID_VideoInputDeviceCategory, L"FriendlyName", strDevice); } if(!deviceFilter) { AppWarning(TEXT("DShowPlugin: Could not create device filter")); goto cleanFinish; } devicePin = GetOutputPin(deviceFilter, &MEDIATYPE_Video); if(!devicePin) { AppWarning(TEXT("DShowPlugin: Could not get device video pin")); goto cleanFinish; } soundOutputType = data->GetInt(TEXT("soundOutputType")); //0 is for backward-compatibility if (strAudioID.CompareI(TEXT("Disabled"))) soundOutputType = 0; if(soundOutputType != 0) { if(!bForceCustomAudio) { err = capture->FindPin(deviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); bDeviceHasAudio = SUCCEEDED(err); } else bDeviceHasAudio = false; if(!bDeviceHasAudio) { if(strDeviceName.IsValid()) { audioDeviceFilter = GetDeviceByValue(CLSID_AudioInputDeviceCategory, L"FriendlyName", strAudioName, L"DevicePath", strAudioID); if(!audioDeviceFilter) AppWarning(TEXT("DShowPlugin: Invalid audio device: name '%s', path '%s'"), strAudioName.Array(), strAudioID.Array()); } else if(strAudioDevice.IsValid()) { audioDeviceFilter = GetDeviceByValue(CLSID_AudioInputDeviceCategory, L"FriendlyName", strAudioDevice); if(!audioDeviceFilter) AppWarning(TEXT("DShowPlugin: Could not create audio device filter")); } if(audioDeviceFilter) err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); else err = E_FAIL; } if(FAILED(err) || !audioPin) { Log(TEXT("DShowPlugin: No audio pin, result = %lX"), err); soundOutputType = 0; } } else bDeviceHasAudio = bForceCustomAudio = false; int soundTimeOffset = data->GetInt(TEXT("soundTimeOffset")); GetOutputList(devicePin, outputList); //------------------------------------------------ // initialize the basic video variables and data renderCX = renderCY = 0; frameInterval = 0; if(bUseCustomResolution) { renderCX = data->GetInt(TEXT("resolutionWidth")); renderCY = data->GetInt(TEXT("resolutionHeight")); frameInterval = data->GetInt(TEXT("frameInterval")); } else { SIZE size; if (!GetClosestResolution(outputList, size, frameInterval)) { AppWarning(TEXT("DShowPlugin: Unable to find appropriate resolution")); renderCX = renderCY = 64; goto cleanFinish; } renderCX = size.cx; renderCY = size.cy; } if(!renderCX || !renderCY || !frameInterval) { AppWarning(TEXT("DShowPlugin: Invalid size/fps specified")); goto cleanFinish; } preferredOutputType = (data->GetInt(TEXT("usePreferredType")) != 0) ? data->GetInt(TEXT("preferredType")) : -1; int numThreads = MAX(OSGetTotalCores()-2, 1); for(int i=0; i<numThreads; i++) { convertData[i].width = renderCX; convertData[i].height = renderCY; convertData[i].sample = NULL; convertData[i].hSignalConvert = CreateEvent(NULL, FALSE, FALSE, NULL); convertData[i].hSignalComplete = CreateEvent(NULL, FALSE, FALSE, NULL); if(i == 0) convertData[i].startY = 0; else convertData[i].startY = convertData[i-1].endY; if(i == (numThreads-1)) convertData[i].endY = renderCY; else convertData[i].endY = ((renderCY/numThreads)*(i+1)) & 0xFFFFFFFE; } bFirstFrame = true; //------------------------------------------------ // get the closest media output for the settings used MediaOutputInfo *bestOutput = GetBestMediaOutput(outputList, renderCX, renderCY, preferredOutputType, frameInterval); if(!bestOutput) { AppWarning(TEXT("DShowPlugin: Could not find appropriate resolution to create device image source")); goto cleanFinish; } //------------------------------------------------ // log video info { String strTest = FormattedString(TEXT(" device: %s,\r\n device id %s,\r\n chosen type: %s, usingFourCC: %s, res: %ux%u - %ux%u, frameIntervals: %llu-%llu"), strDevice.Array(), strDeviceID.Array(), EnumToName[(int)bestOutput->videoType], bestOutput->bUsingFourCC ? TEXT("true") : TEXT("false"), bestOutput->minCX, bestOutput->minCY, bestOutput->maxCX, bestOutput->maxCY, bestOutput->minFrameInterval, bestOutput->maxFrameInterval); BITMAPINFOHEADER *bmiHeader = GetVideoBMIHeader(bestOutput->mediaType); char fourcc[5]; mcpy(fourcc, &bmiHeader->biCompression, 4); fourcc[4] = 0; if(bmiHeader->biCompression > 1000) strTest << FormattedString(TEXT(", fourCC: '%S'\r\n"), fourcc); else strTest << FormattedString(TEXT(", fourCC: %08lX\r\n"), bmiHeader->biCompression); if(!bDeviceHasAudio) strTest << FormattedString(TEXT(" audio device: %s,\r\n audio device id %s,\r\n"), strAudioDevice.Array(), strAudioID.Array()); Log(TEXT("------------------------------------------")); Log(strTest.Array()); } //------------------------------------------------ // set up shaders and video output data expectedMediaType = bestOutput->mediaType->subtype; colorType = DeviceOutputType_RGB; if(bestOutput->videoType == VideoOutputType_I420) colorType = DeviceOutputType_I420; else if(bestOutput->videoType == VideoOutputType_YV12) colorType = DeviceOutputType_YV12; else if(bestOutput->videoType == VideoOutputType_YVYU) colorType = DeviceOutputType_YVYU; else if(bestOutput->videoType == VideoOutputType_YUY2) colorType = DeviceOutputType_YUY2; else if(bestOutput->videoType == VideoOutputType_UYVY) colorType = DeviceOutputType_UYVY; else if(bestOutput->videoType == VideoOutputType_HDYC) colorType = DeviceOutputType_HDYC; else { colorType = DeviceOutputType_RGB; expectedMediaType = MEDIASUBTYPE_RGB32; } strShader = ChooseShader(); if(strShader.IsValid()) colorConvertShader = CreatePixelShaderFromFile(strShader); if(colorType != DeviceOutputType_RGB && !colorConvertShader) { AppWarning(TEXT("DShowPlugin: Could not create color space conversion pixel shader")); goto cleanFinish; } if(colorType == DeviceOutputType_YV12 || colorType == DeviceOutputType_I420) { for(int i=0; i<numThreads; i++) hConvertThreads[i] = OSCreateThread((XTHREAD)PackPlanarThread, convertData+i); } //------------------------------------------------ // set chroma details keyBaseColor = Color4().MakeFromRGBA(keyColor); Matrix4x4TransformVect(keyChroma, (colorType == DeviceOutputType_HDYC) ? (float*)yuv709Mat : (float*)yuvMat, keyBaseColor); keyChroma *= 2.0f; //------------------------------------------------ // configure video pin if(FAILED(err = devicePin->QueryInterface(IID_IAMStreamConfig, (void**)&config))) { AppWarning(TEXT("DShowPlugin: Could not get IAMStreamConfig for device pin, result = %08lX"), err); goto cleanFinish; } AM_MEDIA_TYPE outputMediaType; CopyMediaType(&outputMediaType, bestOutput->mediaType); VIDEOINFOHEADER *vih = reinterpret_cast<VIDEOINFOHEADER*>(outputMediaType.pbFormat); BITMAPINFOHEADER *bmi = GetVideoBMIHeader(&outputMediaType); vih->AvgTimePerFrame = frameInterval; bmi->biWidth = renderCX; bmi->biHeight = renderCY; bmi->biSizeImage = renderCX*renderCY*(bmi->biBitCount>>3); if(FAILED(err = config->SetFormat(&outputMediaType))) { if(err != E_NOTIMPL) { AppWarning(TEXT("DShowPlugin: SetFormat on device pin failed, result = %08lX"), err); goto cleanFinish; } } FreeMediaType(outputMediaType); //------------------------------------------------ // get audio pin configuration, optionally configure audio pin to 44100 GUID expectedAudioType; if(soundOutputType == 1) { IAMStreamConfig *audioConfig; if(SUCCEEDED(audioPin->QueryInterface(IID_IAMStreamConfig, (void**)&audioConfig))) { AM_MEDIA_TYPE *audioMediaType; if(SUCCEEDED(err = audioConfig->GetFormat(&audioMediaType))) { SetAudioInfo(audioMediaType, expectedAudioType); } else if(err == E_NOTIMPL) //elgato probably { IEnumMediaTypes *audioMediaTypes; if(SUCCEEDED(err = audioPin->EnumMediaTypes(&audioMediaTypes))) { ULONG i = 0; if((err = audioMediaTypes->Next(1, &audioMediaType, &i)) == S_OK) SetAudioInfo(audioMediaType, expectedAudioType); else { AppWarning(TEXT("DShowPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } audioMediaTypes->Release(); } else { AppWarning(TEXT("DShowPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } } else { AppWarning(TEXT("DShowPlugin: Could not get audio format, result = %08lX"), err); soundOutputType = 0; } audioConfig->Release(); } else { soundOutputType = 0; } } //------------------------------------------------ // add video capture filter if any captureFilter = new CaptureFilter(this, MEDIATYPE_Video, expectedMediaType); if(FAILED(err = graph->AddFilter(captureFilter, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to add video capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedVideoCapture = true; //------------------------------------------------ // add audio capture filter if any if(soundOutputType == 1) { audioFilter = new CaptureFilter(this, MEDIATYPE_Audio, expectedAudioType); if(!audioFilter) { AppWarning(TEXT("Failed to create audio capture filter")); soundOutputType = 0; } } else if(soundOutputType == 2) { if(FAILED(err = CoCreateInstance(CLSID_AudioRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&audioFilter))) { AppWarning(TEXT("DShowPlugin: failed to create audio renderer, result = %08lX"), err); soundOutputType = 0; } IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(volume)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } if(soundOutputType != 0) { if(FAILED(err = graph->AddFilter(audioFilter, NULL))) AppWarning(TEXT("DShowPlugin: Failed to add audio capture filter to graph, result = %08lX"), err); bAddedAudioCapture = true; } //------------------------------------------------ // add primary device filter if(FAILED(err = graph->AddFilter(deviceFilter, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to add device filter to graph, result = %08lX"), err); goto cleanFinish; } if(soundOutputType != 0 && !bDeviceHasAudio) { if(FAILED(err = graph->AddFilter(audioDeviceFilter, NULL))) AppWarning(TEXT("DShowPlugin: Failed to add audio device filter to graph, result = %08lX"), err); } bAddedDevice = true; //------------------------------------------------ // connect all pins and set up the whole capture thing //THANK THE NINE DIVINES I FINALLY GOT IT WORKING bool bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, deviceFilter, NULL, captureFilter)); if(!bConnected) { if(FAILED(err = graph->Connect(devicePin, captureFilter->GetCapturePin()))) { AppWarning(TEXT("DShowPlugin: Failed to connect the video device pin to the video capture pin, result = %08lX"), err); goto cleanFinish; } } if(soundOutputType != 0) { if(!bDeviceHasAudio) bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, audioDeviceFilter, NULL, audioFilter)); else bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, deviceFilter, NULL, audioFilter)); if(!bConnected) { AppWarning(TEXT("DShowPlugin: Failed to connect the audio device pin to the audio capture pin, result = %08lX"), err); soundOutputType = 0; } } if(FAILED(err = graph->QueryInterface(IID_IMediaControl, (void**)&control))) { AppWarning(TEXT("DShowPlugin: Failed to get IMediaControl, result = %08lX"), err); goto cleanFinish; } if (bUseBuffering) { if (!(hStopSampleEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to create stop event"), err); goto cleanFinish; } if (!(hSampleThread = OSCreateThread((XTHREAD)SampleThread, this))) { AppWarning(TEXT("DShowPlugin: Failed to create sample thread"), err); goto cleanFinish; } } if(soundOutputType == 1) { audioOut = new DeviceAudioSource; audioOut->Initialize(this); API->AddAudioSource(audioOut); audioOut->SetAudioOffset(soundTimeOffset); audioOut->SetVolume(volume); } bSucceeded = true; cleanFinish: SafeRelease(config); SafeRelease(devicePin); SafeRelease(audioPin); for(UINT i=0; i<outputList.Num(); i++) outputList[i].FreeData(); if(!bSucceeded) { bCapturing = false; if(bAddedVideoCapture) graph->RemoveFilter(captureFilter); if(bAddedAudioCapture) graph->RemoveFilter(audioFilter); if(bAddedDevice) { if(!bDeviceHasAudio && audioDeviceFilter) graph->RemoveFilter(audioDeviceFilter); graph->RemoveFilter(deviceFilter); } SafeRelease(audioDeviceFilter); SafeRelease(deviceFilter); SafeRelease(captureFilter); SafeRelease(audioFilter); SafeRelease(control); if (hSampleThread) { SetEvent(hStopSampleEvent); WaitForSingleObject(hSampleThread, INFINITE); CloseHandle(hSampleThread); hSampleThread = NULL; } if (hStopSampleEvent) { CloseHandle(hStopSampleEvent); hStopSampleEvent = NULL; } if(colorConvertShader) { delete colorConvertShader; colorConvertShader = NULL; } if(audioOut) { delete audioOut; audioOut = NULL; } if(lpImageBuffer) { Free(lpImageBuffer); lpImageBuffer = NULL; } bReadyToDraw = true; } else bReadyToDraw = false; if(!renderCX) renderCX = 32; if(!renderCY) renderCY = 32; //----------------------------------------------------- // create the texture regardless, will just show up as red to indicate failure BYTE *textureData = (BYTE*)Allocate(renderCX*renderCY*4); if(colorType == DeviceOutputType_RGB) //you may be confused, but when directshow outputs RGB, it's actually outputting BGR { msetd(textureData, 0xFFFF0000, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE); } else //if we're working with planar YUV, we can just use regular RGB textures instead { msetd(textureData, 0xFF0000FF, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE); } if(bSucceeded && bUseThreadedConversion) { if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12) { LPBYTE lpData; if(texture->Map(lpData, texturePitch)) texture->Unmap(); else texturePitch = renderCX*4; lpImageBuffer = (LPBYTE)Allocate(texturePitch*renderCY); } } Free(textureData); bFiltersLoaded = bSucceeded; return bSucceeded; }
void DeviceSource::Preprocess() { if(!bCapturing) return; //---------------------------------------- if(bRequestVolume) { if(audioOut) audioOut->SetVolume(fNewVol); else if(audioFilter) { IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(fNewVol)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } bRequestVolume = false; } //---------------------------------------- SampleData *lastSample = NULL; OSEnterMutex(hSampleMutex); lastSample = latestVideoSample; latestVideoSample = NULL; OSLeaveMutex(hSampleMutex); //---------------------------------------- int numThreads = MAX(OSGetTotalCores()-2, 1); if(lastSample) { /*REFERENCE_TIME refTimeStart, refTimeFinish; lastSample->GetTime(&refTimeStart, &refTimeFinish); static REFERENCE_TIME lastRefTime = 0; Log(TEXT("refTimeStart: %llu, refTimeFinish: %llu, offset = %llu"), refTimeStart, refTimeFinish, refTimeStart-lastRefTime); lastRefTime = refTimeStart;*/ if(colorType == DeviceOutputType_RGB) { if(texture) { texture->SetImage(lastSample->lpData, GS_IMAGEFORMAT_BGRX, renderCX*4); bReadyToDraw = true; } } else if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12) { if(bUseThreadedConversion) { if(!bFirstFrame) { List<HANDLE> events; for(int i=0; i<numThreads; i++) events << convertData[i].hSignalComplete; WaitForMultipleObjects(numThreads, events.Array(), TRUE, INFINITE); texture->SetImage(lpImageBuffer, GS_IMAGEFORMAT_RGBX, texturePitch); bReadyToDraw = true; } else bFirstFrame = false; for(int i=0; i<numThreads; i++) lastSample->AddRef(); for(int i=0; i<numThreads; i++) { convertData[i].input = lastSample->lpData; convertData[i].sample = lastSample; convertData[i].pitch = texturePitch; convertData[i].output = lpImageBuffer; SetEvent(convertData[i].hSignalConvert); } } else { LPBYTE lpData; UINT pitch; if(texture->Map(lpData, pitch)) { PackPlanar(lpData, lastSample->lpData, renderCX, renderCY, pitch, 0, renderCY); texture->Unmap(); } bReadyToDraw = true; } } else if(colorType == DeviceOutputType_YVYU || colorType == DeviceOutputType_YUY2) { LPBYTE lpData; UINT pitch; if(texture->Map(lpData, pitch)) { Convert422To444(lpData, lastSample->lpData, pitch, true); texture->Unmap(); } bReadyToDraw = true; } else if(colorType == DeviceOutputType_UYVY || colorType == DeviceOutputType_HDYC) { LPBYTE lpData; UINT pitch; if(texture->Map(lpData, pitch)) { Convert422To444(lpData, lastSample->lpData, pitch, false); texture->Unmap(); } bReadyToDraw = true; } lastSample->Release(); } }
// Open multimedia stream. BOOL CDShow::Open(ZString& pFileName, IDirectDraw7 *pDD) { // Multimedia stream pointer IAMMultiMediaStream *pAMStream; IGraphBuilder *pGb; // 7/10 #110 IEnumFilters *pEfs; IBasicAudio *pBa; //7/29/09 we can now do stuff while the video plays CoInitializeEx(NULL,COINIT_MULTITHREADED); // Create Multimedia stream object if (FAILED(CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, (void **)&pAMStream))) { // Return FALSE to let caller know we failed. return FALSE; } // Initialize Multimedia stream object if (FAILED(pAMStream->Initialize(STREAMTYPE_READ, 0, NULL))) { // There are alot of possiblities to fail..... return FALSE; } // Add primary video stream. if (FAILED((pAMStream->AddMediaStream(pDD, &MSPID_PrimaryVideo, 0, NULL)))) { return FALSE; } // Add default sound render to primary video stream, // so sound will be played back automatically. if (FAILED(pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL))) { // Return FALSE to let caller know we failed. return FALSE; } // Convert filename to UNICODE. // Notice the safe way to get the actual size of a string. WCHAR wPath[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, pFileName, -1, wPath, sizeof(wPath)/sizeof(wPath[0])); // Build the filter graph for our multimedia stream. if (FAILED((pAMStream->OpenFile(wPath, 0)))) { // Return FALSE to let caller know we failed. return FALSE; } //7/10 #110 FILTER_INFO FilterInfo; pAMStream->GetFilterGraph(&pGb); pGb->EnumFilters(&pEfs); IBaseFilter *pFilter; unsigned long cFetched; while(pEfs->Next(1, &pFilter, &cFetched) == S_OK) { FILTER_INFO FilterInfo; pFilter->QueryFilterInfo(&FilterInfo); char szName[MAX_FILTER_NAME]; long cch = WideCharToMultiByte(CP_ACP,0,FilterInfo.achName,MAX_FILTER_NAME,szName,MAX_FILTER_NAME,0,0); if (cch > 0) { if (!strcmp("WMAudio Decoder DMO",szName)) { // set the volume to music level FilterInfo.pGraph->QueryInterface(IID_IBasicAudio,(void**)&pBa); HKEY hKey; DWORD dwResult = 0; if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT,0, KEY_READ, &hKey)) { DWORD dwSize = sizeof(dwResult); DWORD dwType = REG_DWORD; ::RegQueryValueEx(hKey, "MusicGain", NULL, &dwType, (BYTE*)&dwResult, &dwSize); ::RegCloseKey(hKey); if (dwType != REG_DWORD) dwResult = 0; } long vol = (dwResult * -1) * 100; if (vol < -5000) { vol = -10000; } pBa->put_Volume(vol); pBa->Release(); } if (FilterInfo.pGraph != NULL) FilterInfo.pGraph->Release(); pFilter->Release(); } } pEfs->Release(); pGb->Release(); // Assign member to temperary stream pointer. m_pMMStream = pAMStream; // Add a reference to the file pAMStream->AddRef(); // Get media stream interface if (FAILED(m_pMMStream->GetMediaStream(MSPID_PrimaryVideo, &m_pPrimaryVideoStream))) { return FALSE; } // Get DirectDraw media stream interface if (FAILED(m_pPrimaryVideoStream->QueryInterface(IID_IDirectDrawMediaStream,(void **)&m_pDDStream))) { return FALSE; } // Create stream sample if (FAILED(m_pDDStream->CreateSample(NULL,NULL,0,&m_pSample))) { return FALSE; } // Get DirectDraw surface interface from Sample. if (FAILED(m_pSample->GetSurface(&m_pDDSurface,&m_rSrcRect))) { return FALSE; } // Get DirectDraw surface7 interface if (FAILED(m_pDDSurface->QueryInterface(IID_IDirectDrawSurface7,(void**)&m_pDDSurface7))) { return FALSE; } // Ok. Media is open now. m_bMediaOpen=TRUE; // If we are here, everything turned out ok. Return TRUE. return TRUE; }