///////////////////////////////////////////////////// // nsIStreamConverterService methods NS_IMETHODIMP nsStreamConverterService::CanConvert(const char* aFromType, const char* aToType, bool* _retval) { nsCOMPtr<nsIComponentRegistrar> reg; nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(reg)); if (NS_FAILED(rv)) return rv; nsAutoCString contractID; contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from="); contractID.Append(aFromType); contractID.AppendLiteral("&to="); contractID.Append(aToType); // See if we have a direct match rv = reg->IsContractIDRegistered(contractID.get(), _retval); if (NS_FAILED(rv)) return rv; if (*_retval) return NS_OK; // Otherwise try the graph. rv = BuildGraph(); if (NS_FAILED(rv)) return rv; nsTArray<nsCString> *converterChain = nullptr; rv = FindConverter(contractID.get(), &converterChain); *_retval = NS_SUCCEEDED(rv); delete converterChain; return NS_OK; }
NS_IMETHODIMP nsStreamConverterService::AsyncConvertData(const char *aFromType, const char *aToType, nsIStreamListener *aListener, nsISupports *aContext, nsIStreamListener **_retval) { if (!aFromType || !aToType || !aListener || !_retval) return NS_ERROR_NULL_POINTER; nsresult rv; // first determine whether we can even handle this conversion // build a CONTRACTID nsAutoCString contractID; contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from="); contractID.Append(aFromType); contractID.AppendLiteral("&to="); contractID.Append(aToType); const char *cContractID = contractID.get(); nsCOMPtr<nsIStreamConverter> listener(do_CreateInstance(cContractID, &rv)); if (NS_FAILED(rv)) { // couldn't go direct, let's try walking the graph of converters. rv = BuildGraph(); if (NS_FAILED(rv)) return rv; nsTArray<nsCString> *converterChain = nullptr; rv = FindConverter(cContractID, &converterChain); if (NS_FAILED(rv)) { // can't make this conversion. // XXX should have a more descriptive error code. return NS_ERROR_FAILURE; } // aListener is the listener that wants the final, converted, data. // we initialize finalListener w/ aListener so it gets put at the // tail end of the chain, which in the loop below, means the *first* // converter created. nsCOMPtr<nsIStreamListener> finalListener = aListener; // convert the stream using each edge of the graph as a step. // this is our stream conversion traversal. int32_t edgeCount = int32_t(converterChain->Length()); NS_ASSERTION(edgeCount > 0, "findConverter should have failed"); for (int i = 0; i < edgeCount; i++) { const char *lContractID = converterChain->ElementAt(i).get(); // create the converter for this from/to pair nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(lContractID)); NS_ASSERTION(converter, "graph construction problem, built a contractid that wasn't registered"); nsAutoCString fromStr, toStr; rv = ParseFromTo(lContractID, fromStr, toStr); if (NS_FAILED(rv)) { delete converterChain; return rv; } // connect the converter w/ the listener that should get the converted data. rv = converter->AsyncConvertData(fromStr.get(), toStr.get(), finalListener, aContext); if (NS_FAILED(rv)) { delete converterChain; return rv; } nsCOMPtr<nsIStreamListener> chainListener(do_QueryInterface(converter, &rv)); if (NS_FAILED(rv)) { delete converterChain; return rv; } // the last iteration of this loop will result in finalListener // pointing to the converter that "starts" the conversion chain. // this converter's "from" type is the original "from" type. Prior // to the last iteration, finalListener will continuously be wedged // into the next listener in the chain, then be updated. finalListener = chainListener; } delete converterChain; // return the first listener in the chain. *_retval = finalListener; NS_ADDREF(*_retval); } else { // we're going direct. *_retval = listener; NS_ADDREF(*_retval); rv = listener->AsyncConvertData(aFromType, aToType, aListener, aContext); } return rv; }
NS_IMETHODIMP nsStreamConverterService::Convert(nsIInputStream *aFromStream, const char *aFromType, const char *aToType, nsISupports *aContext, nsIInputStream **_retval) { if (!aFromStream || !aFromType || !aToType || !_retval) return NS_ERROR_NULL_POINTER; nsresult rv; // first determine whether we can even handle this conversion // build a CONTRACTID nsAutoCString contractID; contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from="); contractID.Append(aFromType); contractID.AppendLiteral("&to="); contractID.Append(aToType); const char *cContractID = contractID.get(); nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(cContractID, &rv)); if (NS_FAILED(rv)) { // couldn't go direct, let's try walking the graph of converters. rv = BuildGraph(); if (NS_FAILED(rv)) return rv; nsTArray<nsCString> *converterChain = nullptr; rv = FindConverter(cContractID, &converterChain); if (NS_FAILED(rv)) { // can't make this conversion. // XXX should have a more descriptive error code. return NS_ERROR_FAILURE; } int32_t edgeCount = int32_t(converterChain->Length()); NS_ASSERTION(edgeCount > 0, "findConverter should have failed"); // convert the stream using each edge of the graph as a step. // this is our stream conversion traversal. nsCOMPtr<nsIInputStream> dataToConvert = aFromStream; nsCOMPtr<nsIInputStream> convertedData; for (int32_t i = edgeCount-1; i >= 0; i--) { const char *lContractID = converterChain->ElementAt(i).get(); converter = do_CreateInstance(lContractID, &rv); if (NS_FAILED(rv)) { delete converterChain; return rv; } nsAutoCString fromStr, toStr; rv = ParseFromTo(lContractID, fromStr, toStr); if (NS_FAILED(rv)) { delete converterChain; return rv; } rv = converter->Convert(dataToConvert, fromStr.get(), toStr.get(), aContext, getter_AddRefs(convertedData)); dataToConvert = convertedData; if (NS_FAILED(rv)) { delete converterChain; return rv; } } delete converterChain; *_retval = convertedData; NS_ADDREF(*_retval); } else { // we're going direct. rv = converter->Convert(aFromStream, aFromType, aToType, aContext, _retval); } return rv; }
module_unneed( p_filter, p_filter->p_module ); vlc_object_release( p_filter ); } } static filter_t *TryFormat (vlc_object_t *obj, vlc_fourcc_t codec, audio_sample_format_t *restrict fmt) { audio_sample_format_t output = *fmt; assert (codec != fmt->i_format); output.i_format = codec; aout_FormatPrepare (&output); filter_t *filter = FindConverter (obj, fmt, &output); if (filter != NULL) *fmt = output; return filter; } /** * Allocates audio format conversion filters * @param obj parent VLC object for new filters * @param filters table of filters [IN/OUT] * @param count pointer to the number of filters in the table [IN/OUT] * @param max size of filters table [IN] * @param infmt input audio format * @param outfmt output audio format * @return 0 on success, -1 on failure */