protected void CreateOutputNode( IMFStreamDescriptor pSourceSD, out IMFTopologyNode ppNode ) { IMFTopologyNode pNode = null; IMFMediaTypeHandler pHandler = null; IMFActivate pRendererActivate = null; Guid guidMajorType = Guid.Empty; MFError throwonhr; // Get the stream ID. int streamID = 0; try { HResult hr; hr = pSourceSD.GetStreamIdentifier(out streamID); // Just for debugging, ignore any failures. if (MFError.Failed(hr)) { //TRACE("IMFStreamDescriptor::GetStreamIdentifier" + hr.ToString()); } // Get the media type handler for the stream. throwonhr = pSourceSD.GetMediaTypeHandler(out pHandler); // Get the major media type. throwonhr = pHandler.GetMajorType(out guidMajorType); // Create a downstream node. throwonhr = MFExtern.MFCreateTopologyNode(MFTopologyType.OutputNode, out pNode); // Create an IMFActivate object for the renderer, based on the media type. if (MFMediaType.Audio == guidMajorType) { // Create the audio renderer. //TRACE(string.Format("Stream {0}: audio stream", streamID)); throwonhr = MFExtern.MFCreateAudioRendererActivate(out pRendererActivate); // Set the IActivate object on the output node. throwonhr = pNode.SetObject(pRendererActivate); } else if (MFMediaType.Video == guidMajorType) { // Create the video renderer. //TRACE(string.Format("Stream {0}: video stream", streamID)); //throwonhr = MFExtern.MFCreateVideoRendererActivate(m_hwndVideo, out pRendererActivate); mIMFTopologyNode.GetObject(out pRendererActivate); throwonhr = pNode.SetObject(pRendererActivate); } else { //TRACE(string.Format("Stream {0}: Unknown format", streamID)); //throw new COMException("Unknown format", (int)HResult.E_FAIL); } // Return the IMFTopologyNode pointer to the caller. ppNode = pNode; } catch { // If we failed, release the pNode //SafeRelease(pNode); throw; } finally { // Clean up. //SafeRelease(pHandler); //SafeRelease(pRendererActivate); } }
// Strings in icy-metaint format. This method called asynchronously by // DoRead(). private void LoadValues(byte[] bData) { // This horrific bit of code is intended to allow for foreign language // character sets. icy provides no way of handling (say) Thai // characters in song titles (and yes, it happens). But you can // set BYTEADJUSTMENT to 0x0e00 and we'll add it to the bytes here. // There's GOT to be a better way... int byteadjustment; HResult hr = GetUINT32(BYTEADJUSTMENT, out byteadjustment); if (MFError.Failed(hr)) { byteadjustment = 0; } // They're really just bytes. I could just as well use ASCII here. string sData = Encoding.UTF8.GetString(bData); // Strings are of the form: // StreamTitle ='something';StreamUrl='somethingelse'; // Assume no spaces around = or ; // Note that there can be (unescaped) embedded ' marks in the // something. Yeah, really. int iPos = sData.IndexOf('='); while (iPos > 0) { // I'm not sure there's any standardization about the case of // property names, so I'm forcing them all to lc. string sKey = FixName(sData.Substring(0, iPos).Trim().ToLower()); iPos++; // skip past equal // I can't think of a more generic way to search // for this. Since ' can be "embedded" in the // string, how do you know where the end of the // string is? int iEnd = sData.IndexOf("';", iPos); // Discard open and close quote string sValue = sData.Substring(iPos + 1, iEnd - iPos - 1).Trim(); StringBuilder value; value = new StringBuilder(sValue); if (byteadjustment != 0) { for (int x = 0; x < value.Length; x++) { value[x] += (char)byteadjustment; } } // Add (or update) the key/value. MFError throwonerror = m_MetaData.SetProperty( sKey, new PropVariant(value.ToString())); // Skip past ' and ; sData = sData.Substring(iEnd + 1 + 1); iPos = sData.IndexOf('='); } // Let anyone who's listening know that there's new metadata. SendEvent(MediaEventType.MESourceMetadataChanged); }