27 #include <sbIGStreamerService.h>
28 #include <sbIMediaFormatMutable.h>
36 #include <nsServiceManagerUtils.h>
37 #include <nsThreadUtils.h>
38 #include <nsStringAPI.h>
41 #include <gst/base/gstadapter.h>
42 #include <gst/app/gstappsink.h>
49 static PRLogModuleInfo* gGStreamerAudioProcessor = PR_NewLogModule(
"sbGStreamerAudioProcessor");
50 #define LOG(args) PR_LOG(gGStreamerAudioProcessor, PR_LOG_WARNING, args)
51 #define TRACE(args) PR_LOG(gGStreamerAudioProcessor, PR_LOG_DEBUG, args)
69 sbGStreamerAudioProcessor::sbGStreamerAudioProcessor() :
71 mConstraintChannelCount(0),
72 mConstraintSampleRate(0),
74 mConstraintBlockSize(0),
75 mConstraintBlockSizeBytes(0),
81 mFoundAudioPad(PR_FALSE),
82 mHasStarted(PR_FALSE),
84 mIsEndOfSection(PR_FALSE),
85 mHasSentError(PR_FALSE),
88 mExpectedNextSampleNumber(0),
97 sbGStreamerAudioProcessor::~sbGStreamerAudioProcessor()
100 nsAutoMonitor::DestroyMonitor(mMonitor);
110 NS_ENSURE_ARG_POINTER(aListener);
111 NS_ENSURE_FALSE(mListener, NS_ERROR_ALREADY_INITIALIZED);
113 mMonitor = nsAutoMonitor::NewMonitor(
"AudioProcessor::mMonitor");
115 mListener = aListener;
121 sbGStreamerAudioProcessor::GetConstraintSampleRate(PRUint32 *aConstraintSampleRate)
123 NS_ENSURE_ARG_POINTER(aConstraintSampleRate);
125 *aConstraintSampleRate = mConstraintSampleRate;
130 sbGStreamerAudioProcessor::SetConstraintSampleRate(PRUint32 aConstraintSampleRate)
132 NS_ENSURE_FALSE(
mPipeline, NS_ERROR_ALREADY_INITIALIZED);
134 mConstraintSampleRate = aConstraintSampleRate;
140 sbGStreamerAudioProcessor::GetConstraintChannelCount(PRUint32 *aConstraintChannelCount)
142 NS_ENSURE_ARG_POINTER(aConstraintChannelCount);
144 *aConstraintChannelCount = mConstraintChannelCount;
149 sbGStreamerAudioProcessor::SetConstraintChannelCount(PRUint32 aConstraintChannelCount)
151 NS_ENSURE_FALSE(
mPipeline, NS_ERROR_ALREADY_INITIALIZED);
154 if (aConstraintChannelCount > 2)
155 return NS_ERROR_INVALID_ARG;
157 mConstraintChannelCount = aConstraintChannelCount;
163 sbGStreamerAudioProcessor::GetConstraintBlockSize(PRUint32 *aConstraintBlockSize)
165 NS_ENSURE_ARG_POINTER(aConstraintBlockSize);
167 *aConstraintBlockSize = mConstraintBlockSize;
172 sbGStreamerAudioProcessor::SetConstraintBlockSize(PRUint32 aConstraintBlockSize)
174 NS_ENSURE_FALSE(
mPipeline, NS_ERROR_ALREADY_INITIALIZED);
176 mConstraintBlockSize = aConstraintBlockSize;
182 sbGStreamerAudioProcessor::GetConstraintAudioFormat(PRUint32 *aConstraintAudioFormat)
184 NS_ENSURE_ARG_POINTER(aConstraintAudioFormat);
186 *aConstraintAudioFormat = mConstraintAudioFormat;
191 sbGStreamerAudioProcessor::SetConstraintAudioFormat(PRUint32 aConstraintAudioFormat)
195 NS_ENSURE_FALSE(
mPipeline, NS_ERROR_ALREADY_INITIALIZED);
197 mConstraintAudioFormat = aConstraintAudioFormat;
205 TRACE((
"%s[%p]", __FUNCTION__,
this));
207 NS_ENSURE_TRUE (NS_IsMainThread(), NS_ERROR_FAILURE);
208 NS_ENSURE_ARG_POINTER (aItem);
209 NS_ENSURE_STATE (mListener);
210 NS_ENSURE_FALSE (
mPipeline, NS_ERROR_FAILURE);
214 nsresult rv = PlayPipeline();
215 NS_ENSURE_SUCCESS(rv, rv);
222 sbGStreamerAudioProcessor::Stop()
224 TRACE((
"%s[%p]", __FUNCTION__,
this));
226 NS_ENSURE_TRUE (NS_IsMainThread(), NS_ERROR_FAILURE);
233 nsresult rv = StopPipeline();
234 NS_ENSURE_SUCCESS(rv, rv);
237 NS_ENSURE_SUCCESS(rv, rv);
244 sbGStreamerAudioProcessor::Suspend()
246 TRACE((
"%s[%p]", __FUNCTION__,
this));
248 NS_ENSURE_TRUE (NS_IsMainThread(), NS_ERROR_FAILURE);
251 nsAutoMonitor mon(mMonitor);
252 mSuspended = PR_TRUE;
258 sbGStreamerAudioProcessor::Resume()
260 TRACE((
"%s[%p]", __FUNCTION__,
this));
262 NS_ENSURE_TRUE (NS_IsMainThread(), NS_ERROR_FAILURE);
265 nsAutoMonitor mon(mMonitor);
266 mSuspended = PR_FALSE;
268 nsresult rv = ScheduleSendDataIfAvailable();
269 NS_ENSURE_SUCCESS(rv, rv);
275 sbGStreamerAudioProcessor::BuildPipeline()
277 TRACE((
"%s[%p]", __FUNCTION__,
this));
294 mPipeline = gst_pipeline_new (
"audio-processor");
295 NS_ENSURE_TRUE (
mPipeline, NS_ERROR_FAILURE);
297 GstElement *uridecodebin = gst_element_factory_make(
299 "audio-processor-decoder");
304 return NS_ERROR_FAILURE;
309 nsresult rv = mMediaItem->GetProperty(
312 NS_ENSURE_SUCCESS(rv, rv);
318 g_object_set (uridecodebin,
"uri",
319 NS_ConvertUTF16toUTF8(contentURL).BeginReading(), NULL);
325 g_signal_connect (uridecodebin,
"pad-added",
326 G_CALLBACK (decodebin_pad_added_cb),
this);
327 g_signal_connect (uridecodebin,
"no-more-pads",
328 G_CALLBACK (decodebin_no_more_pads_cb),
this);
330 gst_bin_add (GST_BIN (
mPipeline), uridecodebin);
332 mAdapter = gst_adapter_new();
338 sbGStreamerAudioProcessor::HandleMessage (GstMessage *
message)
343 GstMessageType msgtype = GST_MESSAGE_TYPE(message);
345 case GST_MESSAGE_ERROR:
348 GError *gerror = NULL;
352 LOG((
"Ignoring multiple error messages"));
356 gst_message_parse_error(message, &gerror, &debug);
358 nsCOMPtr<sbIMediacoreError> error;
361 getter_AddRefs(error));
362 NS_ENSURE_SUCCESS(rv, );
366 NS_ENSURE_SUCCESS(rv, );
368 g_error_free (gerror);
371 mHasSentError = PR_TRUE;
376 LOG((
"Ignoring message: %s", gst_message_type_get_name(msgtype)));
382 sbGStreamerAudioProcessor::decodebin_pad_added_cb (
383 GstElement * uridecodebin,
387 nsresult rv = processor->DecoderPadAdded(uridecodebin, pad);
388 NS_ENSURE_SUCCESS (rv, );
392 sbGStreamerAudioProcessor::decodebin_no_more_pads_cb (
393 GstElement * uridecodebin,
396 nsresult rv = processor->DecoderNoMorePads(uridecodebin);
397 NS_ENSURE_SUCCESS (rv, );
401 sbGStreamerAudioProcessor::appsink_new_buffer_cb (
402 GstElement * appsink,
405 nsresult rv = processor->AppsinkNewBuffer(appsink);
406 NS_ENSURE_SUCCESS (rv, );
410 sbGStreamerAudioProcessor::appsink_eos_cb (
411 GstElement * appsink,
414 nsresult rv = processor->AppsinkEOS(appsink);
415 NS_ENSURE_SUCCESS (rv, );
419 sbGStreamerAudioProcessor::DecoderPadAdded (GstElement *uridecodebin,
422 TRACE((
"%s[%p]", __FUNCTION__,
this));
427 GstCaps *caps = gst_pad_get_caps (pad);
428 GstStructure *structure = gst_caps_get_structure (caps, 0);
429 const gchar *
name = gst_structure_get_name (structure);
430 bool isAudio = g_str_has_prefix (name,
"audio/");
432 gst_caps_unref (caps);
435 LOG((
"Ignoring non audio pad"));
439 if (mFoundAudioPad) {
440 LOG((
"Ignoring additional audio pad"));
444 mFoundAudioPad = PR_TRUE;
447 GstElement *audioconvert = NULL;
448 GstElement *audioresample = NULL;
449 GstElement *capsfilter = NULL;
450 GstElement *appsink = NULL;
453 audioconvert = gst_element_factory_make(
"audioconvert", NULL);
454 audioresample = gst_element_factory_make(
"audioresample", NULL);
455 capsfilter = gst_element_factory_make(
"capsfilter", NULL);
456 appsink = gst_element_factory_make(
"appsink", NULL);
458 if (!audioconvert || !audioresample || !capsfilter || !appsink) {
459 LOG((
"Missing base elements, corrupt GStreamer install"));
463 rv = ConfigureInitialCapsfilter(capsfilter);
464 NS_ENSURE_SUCCESS(rv, rv);
470 g_object_set (appsink,
471 "emit-signals", TRUE,
475 g_signal_connect (appsink,
"new-buffer",
476 G_CALLBACK (appsink_new_buffer_cb),
this);
477 g_signal_connect (appsink,
"eos",
478 G_CALLBACK (appsink_eos_cb),
this);
481 audioconvert, audioresample, capsfilter, appsink, NULL);
482 gst_element_link_many (audioconvert, audioresample, capsfilter, appsink, NULL);
484 sinkpad = gst_element_get_static_pad (audioconvert,
"sink");
485 gst_pad_link (pad, sinkpad);
486 gst_object_unref (sinkpad);
488 gst_element_set_state (audioconvert, GST_STATE_PLAYING);
489 gst_element_set_state (audioresample, GST_STATE_PLAYING);
490 gst_element_set_state (capsfilter, GST_STATE_PLAYING);
491 gst_element_set_state (appsink, GST_STATE_PLAYING);
493 mAppSink = (GstAppSink *)gst_object_ref (appsink);
494 mCapsFilter = (GstElement *)gst_object_ref (capsfilter);
500 g_object_unref (audioconvert);
502 g_object_unref (audioresample);
504 g_object_unref (capsfilter);
506 g_object_unref (appsink);
508 return NS_ERROR_FAILURE;
512 sbGStreamerAudioProcessor::OnDestroyPipeline(GstElement *pipeline)
515 gst_object_unref (mAppSink);
519 gst_object_unref (mCapsFilter);
524 g_object_unref (mAdapter);
528 if (mPendingBuffer) {
529 gst_buffer_unref (mPendingBuffer);
530 mPendingBuffer = NULL;
534 mSuspended = PR_FALSE;
535 mFoundAudioPad = PR_FALSE;
536 mHasStarted = PR_FALSE;
538 mIsEndOfSection = PR_FALSE;
539 mHasSentError = PR_FALSE;
542 mExpectedNextSampleNumber = 0;
546 mBuffersAvailable = 0;
552 sbGStreamerAudioProcessor::ConfigureInitialCapsfilter(GstElement *capsfilter)
554 TRACE((
"%s[%p]", __FUNCTION__,
this));
557 GstStructure *structure;
559 caps = gst_caps_new_empty ();
563 structure = gst_structure_new (
"audio/x-raw-int",
564 "endianness", G_TYPE_INT, G_BYTE_ORDER,
565 "width", G_TYPE_INT, 16,
566 "depth", G_TYPE_INT, 16,
568 if (mConstraintSampleRate) {
569 gst_structure_set(structure,
570 "rate", G_TYPE_INT, mConstraintSampleRate, NULL);
573 if (mConstraintChannelCount) {
574 gst_structure_set(structure,
575 "channels", G_TYPE_INT, mConstraintChannelCount, NULL);
580 gst_structure_set(structure,
"channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
582 gst_caps_append_structure (caps, structure);
588 structure = gst_structure_new (
"audio/x-raw-float",
589 "endianness", G_TYPE_INT, G_BYTE_ORDER,
590 "width", G_TYPE_INT, 32,
592 if (mConstraintSampleRate) {
593 gst_structure_set(structure,
594 "rate", G_TYPE_INT, mConstraintSampleRate, NULL);
597 if (mConstraintChannelCount) {
598 gst_structure_set(structure,
599 "channels", G_TYPE_INT, mConstraintChannelCount, NULL);
604 gst_structure_set(structure,
"channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
606 gst_caps_append_structure (caps, structure);
609 g_object_set (capsfilter,
"caps", caps, NULL);
615 sbGStreamerAudioProcessor::ReconfigureCapsfilter()
617 TRACE((
"%s[%p]", __FUNCTION__,
this));
622 caps = gst_caps_new_simple (
"audio/x-raw-int",
623 "endianness", G_TYPE_INT, G_BYTE_ORDER,
624 "width", G_TYPE_INT, 16,
625 "depth", G_TYPE_INT, 16,
626 "rate", G_TYPE_INT, mSampleRate,
627 "channels", G_TYPE_INT, mChannels,
631 caps = gst_caps_new_simple (
"audio/x-raw-float",
632 "endianness", G_TYPE_INT, G_BYTE_ORDER,
633 "width", G_TYPE_INT, 32,
634 "rate", G_TYPE_INT, mSampleRate,
635 "channels", G_TYPE_INT, mChannels,
639 g_object_set (mCapsFilter,
"caps", caps, NULL);
645 sbGStreamerAudioProcessor::DecoderNoMorePads (GstElement *uridecodebin)
647 TRACE((
"%s[%p]", __FUNCTION__,
this));
649 if (!mFoundAudioPad) {
652 "mediacore.error.wrong_type");
653 NS_ENSURE_SUCCESS(rv, rv);
660 sbGStreamerAudioProcessor::HasEnoughData()
662 TRACE((
"%s[%p]", __FUNCTION__,
this));
664 nsAutoMonitor mon(mMonitor);
666 guint available = gst_adapter_available (mAdapter);
676 return (available > 0 &&
677 ((mIsEOS && !mBuffersAvailable) ||
679 available >= mConstraintBlockSizeBytes));
683 sbGStreamerAudioProcessor::GetSampleNumberFromBuffer(GstBuffer *buf)
685 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buf);
686 if (timestamp == GST_CLOCK_TIME_NONE) {
688 return mExpectedNextSampleNumber;
691 return gst_util_uint64_scale_int_round (timestamp, mSampleRate, GST_SECOND) *
696 sbGStreamerAudioProcessor::GetDurationFromBuffer(GstBuffer *buf)
700 size =
sizeof(float);
702 size =
sizeof(short);
704 return GST_BUFFER_SIZE (buf) / size;
708 sbGStreamerAudioProcessor::GetMoreData()
710 TRACE((
"%s[%p]", __FUNCTION__,
this));
712 nsAutoMonitor mon(mMonitor);
714 NS_ENSURE_TRUE (mBuffersAvailable > 0, );
716 if (mPendingBuffer) {
719 NS_ASSERTION(gst_adapter_available(mAdapter) == 0,
720 "Had pending buffer but asked to get more data when adapter not empty");
722 mSampleNumber = GetSampleNumberFromBuffer(mPendingBuffer);
723 gst_adapter_push(mAdapter, mPendingBuffer);
725 mExpectedNextSampleNumber = mSampleNumber +
726 GetDurationFromBuffer(mPendingBuffer);
729 mPendingBuffer = NULL;
730 mIsEndOfSection = PR_FALSE;
733 GstBuffer *buf = gst_app_sink_pull_buffer(mAppSink);
734 NS_ASSERTION(buf,
"pulled buffer when asked to get more but got no buffer");
738 PRUint64 nextSampleNumber = GetSampleNumberFromBuffer(buf);
739 if (nextSampleNumber != mExpectedNextSampleNumber ||
740 (GST_BUFFER_IS_DISCONT (buf) && mExpectedNextSampleNumber != 0))
742 LOG((
"Discontinuity found"));
745 mPendingBuffer = buf;
746 mIsEndOfSection = PR_TRUE;
751 if (gst_adapter_available(mAdapter) == 0)
752 mSampleNumber = nextSampleNumber;
753 gst_adapter_push(mAdapter, buf);
754 mExpectedNextSampleNumber += GetDurationFromBuffer(buf);
760 sbGStreamerAudioProcessor::AppsinkNewBuffer(GstElement *appsink)
763 nsAutoMonitor mon(mMonitor);
768 rv = DetermineFormat();
769 NS_ENSURE_SUCCESS(rv, rv);
774 if (!HasEnoughData()) {
777 if (HasEnoughData()) {
778 rv = ScheduleSendData();
779 NS_ENSURE_SUCCESS(rv, rv);
787 sbGStreamerAudioProcessor::ScheduleSendDataIfAvailable()
789 TRACE((
"%s[%p]", __FUNCTION__,
this));
793 nsAutoMonitor mon(mMonitor);
795 if (HasEnoughData()) {
796 rv = ScheduleSendData();
797 NS_ENSURE_SUCCESS(rv, rv);
801 while(mBuffersAvailable) {
804 if (HasEnoughData()) {
805 rv = ScheduleSendData();
806 NS_ENSURE_SUCCESS(rv, rv);
814 NS_ENSURE_SUCCESS(rv, rv);
821 sbGStreamerAudioProcessor::ScheduleSendData()
823 TRACE((
"%s[%p]", __FUNCTION__,
this));
825 nsCOMPtr<nsIThread> mainThread;
826 nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
827 NS_ENSURE_SUCCESS(rv, rv);
829 nsCOMPtr<nsIRunnable> runnable =
831 NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
833 rv = mainThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
834 NS_ENSURE_SUCCESS(rv, rv);
840 sbGStreamerAudioProcessor::DetermineFormat()
842 GstPad *appsinkSinkPad = gst_element_get_static_pad (GST_ELEMENT (mAppSink),
844 GstCaps *caps = gst_pad_get_negotiated_caps(appsinkSinkPad);
846 return NS_ERROR_FAILURE;
848 GstStructure *structure = gst_caps_get_structure(caps, 0);
849 const gchar *capsName = gst_structure_get_name (structure);
851 if (g_str_equal(capsName,
"audio/x-raw-float")) {
853 mConstraintBlockSizeBytes = mConstraintBlockSize *
sizeof(float);
857 mConstraintBlockSizeBytes = mConstraintBlockSize *
sizeof(short);
860 gst_structure_get_int (structure,
"rate", &mSampleRate);
861 gst_structure_get_int (structure,
"channels", &mChannels);
863 gst_caps_unref (caps);
867 nsresult rv = ReconfigureCapsfilter();
868 NS_ENSURE_SUCCESS(rv, rv);
874 sbGStreamerAudioProcessor::DoStreamStart()
877 nsCOMPtr<sbIMediaFormatAudioMutable> audioFormat =
879 NS_ENSURE_SUCCESS(rv, rv);
881 rv = audioFormat->SetAudioType(NS_LITERAL_STRING (
"audio/x-raw"));
882 NS_ENSURE_SUCCESS(rv, rv);
883 rv = audioFormat->SetSampleRate(mSampleRate);
884 NS_ENSURE_SUCCESS(rv, rv);
885 rv = audioFormat->SetChannels(mChannels);
886 NS_ENSURE_SUCCESS(rv, rv);
888 nsCOMPtr<nsISupports> audioFormatISupports = do_QueryInterface(audioFormat,
890 NS_ENSURE_SUCCESS(rv, rv);
894 NS_ENSURE_SUCCESS(rv, rv);
900 sbGStreamerAudioProcessor::SendDataToListener()
906 nsAutoMonitor mon(mMonitor);
913 NS_ASSERTION(HasEnoughData(),
"Asked to send data, but cannot");
919 mHasStarted = PR_TRUE;
923 rv = DoStreamStart();
924 NS_ENSURE_SUCCESS(rv, );
928 if (!mHasStarted || mSuspended) {
934 guint available = gst_adapter_available (mAdapter);
935 if (mConstraintBlockSize == 0)
936 bytesRead = available;
937 else if (available >= mConstraintBlockSizeBytes)
938 bytesRead = mConstraintBlockSizeBytes;
939 else if (mIsEOS || mIsEndOfSection)
940 bytesRead = available;
942 NS_NOTREACHED(
"not enough data here");
944 data = gst_adapter_peek(mAdapter, bytesRead);
946 PRUint32 sampleNumber = mSampleNumber;
949 PRBool sendGap = mSendGap;
957 NS_ENSURE_SUCCESS(rv, );
961 numSamples = bytesRead /
sizeof(PRInt16);
962 PRInt16 *sampleData = (PRInt16 *)data;
964 rv = mListener->OnIntegerAudioDecoded(sampleNumber, numSamples, sampleData);
967 numSamples = bytesRead /
sizeof(float);
968 float *sampleData = (
float *)data;
970 rv = mListener->OnFloatAudioDecoded(sampleNumber, numSamples, sampleData);
974 NS_WARNING(
"Listener failed to receive data");
984 mSampleNumber += numSamples;
986 gst_adapter_flush(mAdapter, bytesRead);
993 rv = ScheduleSendDataIfAvailable();
994 NS_ENSURE_SUCCESS(rv, );
998 sbGStreamerAudioProcessor::AppsinkEOS(GstElement *appsink)
1000 TRACE((
"%s[%p]", __FUNCTION__,
this));
1004 nsAutoMonitor mon(mMonitor);
1008 if (!HasEnoughData()) {
1014 if (HasEnoughData()) {
1015 rv = ScheduleSendData();
1016 NS_ENSURE_SUCCESS(rv, rv);
1022 NS_ENSURE_SUCCESS(rv, rv);
1024 else if (!mHasSentError) {
1028 "mediacore.error.decode_failed");
1029 NS_ENSURE_SUCCESS(rv, rv);
1041 sbGStreamerAudioProcessor::SendErrorEvent(PRUint32 errorCode,
1042 const char *errorName)
1044 TRACE((
"%s[%p]", __FUNCTION__,
this));
1047 nsString errorMessage = bundle.
Get(errorName);
1049 nsRefPtr<sbMediacoreError> error;
1051 error->Init(errorCode, errorMessage);
1055 NS_ENSURE_SUCCESS(rv, rv);
1061 sbGStreamerAudioProcessor::SendEventInternal(PRUint32 eventType,
1062 nsCOMPtr<nsIVariant> eventDetails)
1066 LOG((
"Sending event of type %d", eventType));
1067 rv = mListener->OnEvent(eventType, eventDetails);
1068 if (NS_FAILED(rv)) {
1069 LOG((
"Listener returned error from OnEvent: %x", rv));
1076 sbGStreamerAudioProcessor::SendEventAsync(PRUint32 eventType,
1077 nsIVariant *eventDetails)
1081 LOG((
"Scheduling sending event of type %d", eventType));
1085 nsCOMPtr<nsIVariant> details(eventDetails);
1087 &sbGStreamerAudioProcessor::SendEventInternal,
1091 NS_ENSURE_SUCCESS(rv, rv);
1096 sbGStreamerAudioProcessor::SendEventSync(PRUint32 eventType,
1097 nsIVariant *eventDetails)
1099 NS_ASSERTION(NS_IsMainThread(),
1100 "SendEventSync() must be called from the main thread");
1101 nsCOMPtr<nsIVariant> details(eventDetails);
1102 nsresult rv = SendEventInternal(eventType, details);
1103 NS_ENSURE_SUCCESS(rv, rv);
NS_DECL_CLASSINFO(sbGstreamerAudioProcessor)
nsString Get(const nsAString &aKey, const nsAString &aDefault=SBVoidString())
NS_IMPL_THREADSAFE_ISUPPORTS3(sbGStreamerAudioProcessor, sbIGStreamerPipeline, sbIMediacoreAudioProcessor, nsIClassInfo) NS_IMPL_CI_INTERFACE_GETTER2(sbGStreamerAudioProcessor
Songbird Variant Utility Definitions.
nsresult sbInvokeOnMainThread2Async(T &aObject, MT aMethod, RT aFailureReturnValue, A1 aArg1, A2 aArg2)
Songbird Thread Utilities Definitions.
NS_IMPL_THREADSAFE_CI(sbGStreamerAudioProcessor)
Songbird String Bundle Definitions.
nsString mResourceDisplayName
NS_IMPL_CI_INTERFACE_GETTER2(sbDataRemoteWrapper, sbIDataRemote, nsIClassInfo) sbDataRemoteWrapper
#define SB_PROPERTY_CONTENTURL
virtual nsresult DestroyPipeline()