void PlayMedia(const char *pszFileName) throw(_com_error) { HRESULT hr; IGraphBuilderPtr pGraphBuilder; IMediaControlPtr pMediaControl; IMediaEventPtr pMediaEvent; WCHAR wszFileName[MAX_PATH]; LONG lEventCode; CoInitializeEx(NULL, COINIT_MULTITHREADED); pGraphBuilder.CreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC); wsprintfW(wszFileName, L"%S", pszFileName); hr = pGraphBuilder->RenderFile(wszFileName, NULL); if (!SUCCEEDED(hr)) _com_raise_error(hr); pMediaControl = pGraphBuilder; pMediaEvent = pGraphBuilder; hr = pMediaControl->Run(); if (!SUCCEEDED(hr)) _com_raise_error(hr); hr = pMediaEvent->WaitForCompletion(INFINITE, &lEventCode); if (!SUCCEEDED(hr)) _com_raise_error(hr); }
int wmain(int argc, wchar_t* argv[]) { using namespace dshow; using namespace std; if (!ParseCommandlineParameters(argc, argv)) { return 1; } try { IGraphBuilderPtr graphBuilder; HRESULT hr = graphBuilder.CreateInstance(CLSID_FilterGraph); ThrowIfError(hr, "ERROR: could not create filter graph object"); IFilterGraphPtr filterGraph = graphBuilder; // Add a renderer, which will be replaced by the encoder IBaseFilterPtr directSound; hr = directSound.CreateInstance(CLSID_DSoundRender); ThrowIfError(hr, "ERROR: could not create direct sound renderer"); filterGraph->AddFilter(directSound, L"Direct Sound Renderer"); // Render the audio source file using intelligent connect hr = graphBuilder->raw_RenderFile(const_cast<wchar_t*>(g_options.sourceFile.c_str()), 0); ThrowIfError(hr, "ERROR: could not render the file"); // Get the audio decoder output pin IPinPtr directSoundRendererInput = FindPin(directSound, dshow::PINDIR_INPUT); IPinPtr audioRendererPin; hr = directSoundRendererInput->raw_ConnectedTo(&audioRendererPin); ThrowIfError(hr, "ERROR: could not get audio renderer output pin"); // Remove the DirectSound renderer audioRendererPin->Disconnect(); filterGraph->RemoveFilter(directSound); // Add the Vorbis Encoder IBaseFilterPtr vorbisEncoder; hr = vorbisEncoder.CreateInstance(CLSID_VorbisEncoder); ThrowIfError(hr, "ERROR: could not create vorbis encoder object"); filterGraph->AddFilter(vorbisEncoder, L"Vorbis Encoder"); // Connect the audio decoder to the Vorbis Encoder IPinPtr vorbisEncoderInput = FindPin(vorbisEncoder, dshow::PINDIR_INPUT); hr = filterGraph->raw_ConnectDirect(audioRendererPin, vorbisEncoderInput, 0); ThrowIfError(hr, "ERROR: could not connect audio renderer to vorbis encoder"); // Add the Ogg Mux Filter IBaseFilterPtr oggMuxer; hr = oggMuxer.CreateInstance(CLSID_OggMuxFilter); ThrowIfError(hr, "ERROR: could not create ogg mux object"); filterGraph->AddFilter(oggMuxer, L"Ogg Muxer"); // Connect the Vorbis Encoder to Ogg Muxer IPinPtr vorbisEncoderOutput = FindPin(vorbisEncoder, dshow::PINDIR_OUTPUT); IPinPtr oggMuxerInput = FindPin(oggMuxer, dshow::PINDIR_INPUT); hr = filterGraph->raw_ConnectDirect(vorbisEncoderOutput, oggMuxerInput, 0); ThrowIfError(hr, "ERROR: could not connect vorbis encoder to ogg muxer"); // Get the encoder settings object IVorbisEncodeSettingsPtr encodeSettings = vorbisEncoder; // Set the name of the Ogg file IFileSinkFilterPtr oggSource = oggMuxer; hr = oggSource->SetFileName(g_options.oggFile.c_str(), 0); ThrowIfError(hr, "ERROR: could not set ogg muxer file"); // Get the progress from the Ogg Muxer IOggMuxProgressPtr oggMuxProgress = oggMuxer; REFERENCE_TIME audioSourceDuration = GetAudioSourceDuration(g_options.sourceFile); wcout << L"Encoding \"" << g_options.sourceFile.c_str() << L"\" to" << endl; wcout << L"\t \"" << g_options.oggFile.c_str() << L"\"" << endl; if (g_options.bitrate != 0) { wcout << L"WARNING: oggcodecs build version <= 0.81.15562 do not work correctly!" << endl; wcout << L"WARNING: at the end of the encoding, the average bitrate does not" << endl; wcout << L"WARNING: have the expected value." << endl; encodeSettings->setBitrateQualityMode(g_options.bitrate); } else if (g_options.managedMinBitrate != 0 && g_options.managedMaxBitrate != 0) { wcout << L"using bitrate management (min " << g_options.managedMinBitrate << L" kbps, "; wcout << L"max " << g_options.managedMaxBitrate << L" kbps)" << endl; encodeSettings->setManaged(g_options.bitrate, g_options.managedMinBitrate, g_options.managedMaxBitrate); } else { wcout << L"at quality " << fixed << setprecision(1) << g_options.quality << endl; encodeSettings->setQuality(static_cast<int>(g_options.quality * 10)); } unsigned long startTime = timeGetTime(); // Start the encoding IMediaControlPtr control = graphBuilder; control->Run(); LONGLONG destinationFileSize; bool isEncoding = true; while (isEncoding) { LONGLONG muxerProgressTime = oggMuxProgress->getProgressTime(); destinationFileSize = oggMuxProgress->getBytesWritten(); // Give a margin of 10 nanoseconds if (muxerProgressTime >= audioSourceDuration - 10) { muxerProgressTime = audioSourceDuration; control->Stop(); isEncoding = false; } else { // Sleep 50 milliseconds Sleep(50); } unsigned long currentTime = ::timeGetTime(); PrintProgress(muxerProgressTime, audioSourceDuration, (currentTime - startTime) * 10000); } unsigned long endTime = timeGetTime(); PrintStatistics(g_options.oggFile, audioSourceDuration, (endTime - startTime) * 10000, destinationFileSize); } catch(const std::runtime_error& err) { wcout << err.what() << endl; } catch(const _com_error& err) { wcout << L"Error code: 0x" << hex << err.Error() << L"(" << err.ErrorMessage() << L")" << endl; } catch (...) { wcout << "Unknown exception!"; } return 0; }