75 } |
75 } |
76 |
76 |
77 diff --git a/content/media/gstreamer/GStreamerReader.cpp b/content/media/gstreamer/GStreamerReader.cpp |
77 diff --git a/content/media/gstreamer/GStreamerReader.cpp b/content/media/gstreamer/GStreamerReader.cpp |
78 --- a/content/media/gstreamer/GStreamerReader.cpp |
78 --- a/content/media/gstreamer/GStreamerReader.cpp |
79 +++ b/content/media/gstreamer/GStreamerReader.cpp |
79 +++ b/content/media/gstreamer/GStreamerReader.cpp |
80 @@ -69,18 +69,22 @@ GStreamerReader::GStreamerReader(Abstrac |
80 @@ -22,16 +22,22 @@ using namespace layers; |
|
81 |
|
82 #ifdef PR_LOGGING |
|
83 extern PRLogModuleInfo* gMediaDecoderLog; |
|
84 #define LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg) |
|
85 #else |
|
86 #define LOG(type, msg) |
|
87 #endif |
|
88 |
|
89 +#if GST_VERSION_MAJOR == 1 |
|
90 +#define PLAYBIN "playbin" |
|
91 +#else |
|
92 +#define PLAYBIN "playbin2" |
|
93 +#endif |
|
94 + |
|
95 static const int MAX_CHANNELS = 4; |
|
96 // Let the demuxer work in pull mode for short files |
|
97 static const int SHORT_FILE_SIZE = 1024 * 1024; |
|
98 // The default resource->Read() size when working in push mode |
|
99 static const int DEFAULT_SOURCE_READ_SIZE = 50 * 1024; |
|
100 |
|
101 typedef enum { |
|
102 GST_PLAY_FLAG_VIDEO = (1 << 0), |
|
103 @@ -69,18 +75,22 @@ GStreamerReader::GStreamerReader(Abstrac |
81 MOZ_COUNT_CTOR(GStreamerReader); |
104 MOZ_COUNT_CTOR(GStreamerReader); |
82 |
105 |
83 mSrcCallbacks.need_data = GStreamerReader::NeedDataCb; |
106 mSrcCallbacks.need_data = GStreamerReader::NeedDataCb; |
84 mSrcCallbacks.enough_data = GStreamerReader::EnoughDataCb; |
107 mSrcCallbacks.enough_data = GStreamerReader::EnoughDataCb; |
85 mSrcCallbacks.seek_data = GStreamerReader::SeekDataCb; |
108 mSrcCallbacks.seek_data = GStreamerReader::SeekDataCb; |
98 } |
121 } |
99 |
122 |
100 GStreamerReader::~GStreamerReader() |
123 GStreamerReader::~GStreamerReader() |
101 { |
124 { |
102 MOZ_COUNT_DTOR(GStreamerReader); |
125 MOZ_COUNT_DTOR(GStreamerReader); |
103 @@ -122,19 +126,26 @@ nsresult GStreamerReader::Init(MediaDeco |
126 @@ -106,60 +116,85 @@ nsresult GStreamerReader::Init(MediaDeco |
|
127 { |
|
128 GError *error = NULL; |
|
129 if (!gst_init_check(0, 0, &error)) { |
|
130 LOG(PR_LOG_ERROR, ("gst initialization failed: %s", error->message)); |
|
131 g_error_free(error); |
|
132 return NS_ERROR_FAILURE; |
|
133 } |
|
134 |
|
135 - mPlayBin = gst_element_factory_make("playbin2", NULL); |
|
136 + mPlayBin = gst_element_factory_make(PLAYBIN, NULL); |
|
137 if (mPlayBin == NULL) { |
|
138 - LOG(PR_LOG_ERROR, ("couldn't create playbin2")); |
|
139 + LOG(PR_LOG_ERROR, ("couldn't create playbin")); |
|
140 return NS_ERROR_FAILURE; |
|
141 } |
|
142 g_object_set(mPlayBin, "buffer-size", 0, NULL); |
|
143 mBus = gst_pipeline_get_bus(GST_PIPELINE(mPlayBin)); |
|
144 |
104 mVideoSink = gst_parse_bin_from_description("capsfilter name=filter ! " |
145 mVideoSink = gst_parse_bin_from_description("capsfilter name=filter ! " |
105 "appsink name=videosink sync=true max-buffers=1 " |
146 "appsink name=videosink sync=true max-buffers=1 " |
|
147 +#if GST_VERSION_MAJOR == 1 |
|
148 + "caps=video/x-raw,format=(fourcc)I420" |
|
149 +#else |
106 "caps=video/x-raw-yuv,format=(fourcc)I420" |
150 "caps=video/x-raw-yuv,format=(fourcc)I420" |
|
151 +#endif |
107 , TRUE, NULL); |
152 , TRUE, NULL); |
108 mVideoAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mVideoSink), |
153 mVideoAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mVideoSink), |
109 "videosink")); |
154 "videosink")); |
110 gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks, |
155 gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks, |
111 (gpointer) this, NULL); |
156 (gpointer) this, NULL); |
122 +#endif |
167 +#endif |
123 gst_object_unref(sinkpad); |
168 gst_object_unref(sinkpad); |
124 |
169 |
125 mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! " |
170 mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! " |
126 #ifdef MOZ_SAMPLE_TYPE_FLOAT32 |
171 #ifdef MOZ_SAMPLE_TYPE_FLOAT32 |
|
172 +#if GST_VERSION_MAJOR == 1 |
|
173 + "appsink name=audiosink sync=true caps=audio/x-raw," |
|
174 +#else |
127 "appsink name=audiosink sync=true caps=audio/x-raw-float," |
175 "appsink name=audiosink sync=true caps=audio/x-raw-float," |
|
176 +#endif |
128 #ifdef IS_LITTLE_ENDIAN |
177 #ifdef IS_LITTLE_ENDIAN |
129 "channels={1,2},width=32,endianness=1234", TRUE, NULL); |
178 "channels={1,2},width=32,endianness=1234", TRUE, NULL); |
130 #else |
179 #else |
131 @@ -147,19 +158,25 @@ nsresult GStreamerReader::Init(MediaDeco |
180 "channels={1,2},width=32,endianness=4321", TRUE, NULL); |
|
181 #endif |
|
182 #else |
|
183 +#if GST_VERSION_MAJOR == 1 |
|
184 + "appsink name=audiosink sync=true caps=audio/x-raw," |
|
185 +#else |
|
186 "appsink name=audiosink sync=true caps=audio/x-raw-int," |
|
187 +#endif |
|
188 #ifdef IS_LITTLE_ENDIAN |
|
189 "channels={1,2},width=16,endianness=1234", TRUE, NULL); |
132 #else |
190 #else |
133 "channels={1,2},width=16,endianness=4321", TRUE, NULL); |
191 "channels={1,2},width=16,endianness=4321", TRUE, NULL); |
134 #endif |
192 #endif |
135 #endif |
193 #endif |
136 mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink), |
194 mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink), |
153 "video-sink", mVideoSink, |
211 "video-sink", mVideoSink, |
154 "audio-sink", mAudioSink, |
212 "audio-sink", mAudioSink, |
155 NULL); |
213 NULL); |
156 |
214 |
157 g_signal_connect(G_OBJECT(mPlayBin), "notify::source", |
215 g_signal_connect(G_OBJECT(mPlayBin), "notify::source", |
158 @@ -236,17 +253,17 @@ nsresult GStreamerReader::ReadMetadata(V |
216 @@ -236,17 +271,17 @@ nsresult GStreamerReader::ReadMetadata(V |
159 filter = gst_bin_get_by_name(GST_BIN(mAudioSink), "filter"); |
217 filter = gst_bin_get_by_name(GST_BIN(mAudioSink), "filter"); |
160 else if (!(current_flags & GST_PLAY_FLAG_VIDEO)) |
218 else if (!(current_flags & GST_PLAY_FLAG_VIDEO)) |
161 filter = gst_bin_get_by_name(GST_BIN(mVideoSink), "filter"); |
219 filter = gst_bin_get_by_name(GST_BIN(mVideoSink), "filter"); |
162 |
220 |
163 if (filter) { |
221 if (filter) { |
172 } |
230 } |
173 |
231 |
174 /* start the pipeline */ |
232 /* start the pipeline */ |
175 gst_element_set_state(mPlayBin, GST_STATE_PAUSED); |
233 gst_element_set_state(mPlayBin, GST_STATE_PAUSED); |
176 |
234 |
177 @@ -289,19 +306,24 @@ nsresult GStreamerReader::ReadMetadata(V |
235 @@ -289,19 +324,24 @@ nsresult GStreamerReader::ReadMetadata(V |
178 gst_element_set_state(mPlayBin, GST_STATE_NULL); |
236 gst_element_set_state(mPlayBin, GST_STATE_NULL); |
179 gst_message_unref(message); |
237 gst_message_unref(message); |
180 return NS_ERROR_FAILURE; |
238 return NS_ERROR_FAILURE; |
181 } |
239 } |
182 } |
240 } |
197 duration = GST_TIME_AS_USECONDS (duration); |
255 duration = GST_TIME_AS_USECONDS (duration); |
198 mDecoder->SetMediaDuration(duration); |
256 mDecoder->SetMediaDuration(duration); |
199 } |
257 } |
200 |
258 |
201 int n_video = 0, n_audio = 0; |
259 int n_video = 0, n_audio = 0; |
202 @@ -370,59 +392,87 @@ bool GStreamerReader::DecodeAudioData() |
260 @@ -370,59 +410,87 @@ bool GStreamerReader::DecodeAudioData() |
203 { |
261 { |
204 NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); |
262 NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); |
205 |
263 |
206 if (!WaitForDecodedData(&mAudioSinkBufferCount)) { |
264 if (!WaitForDecodedData(&mAudioSinkBufferCount)) { |
207 mAudioQueue.Finish(); |
265 mAudioQueue.Finish(); |
285 |
343 |
286 timestamp = GST_BUFFER_TIMESTAMP(buffer); |
344 timestamp = GST_BUFFER_TIMESTAMP(buffer); |
287 { |
345 { |
288 ReentrantMonitorAutoEnter mon(mGstThreadsMonitor); |
346 ReentrantMonitorAutoEnter mon(mGstThreadsMonitor); |
289 timestamp = gst_segment_to_stream_time(&mVideoSegment, |
347 timestamp = gst_segment_to_stream_time(&mVideoSegment, |
290 @@ -436,62 +486,90 @@ bool GStreamerReader::DecodeVideoFrame(b |
348 @@ -436,62 +504,90 @@ bool GStreamerReader::DecodeVideoFrame(b |
291 else if (fpsNum && fpsDen) |
349 else if (fpsNum && fpsDen) |
292 /* add 1-frame duration */ |
350 /* add 1-frame duration */ |
293 nextTimestamp += gst_util_uint64_scale(GST_USECOND, fpsNum, fpsDen); |
351 nextTimestamp += gst_util_uint64_scale(GST_USECOND, fpsNum, fpsDen); |
294 |
352 |
295 if (timestamp < aTimeThreshold) { |
353 if (timestamp < aTimeThreshold) { |
376 |
434 |
377 nsresult GStreamerReader::Seek(int64_t aTarget, |
435 nsresult GStreamerReader::Seek(int64_t aTarget, |
378 int64_t aStartTime, |
436 int64_t aStartTime, |
379 int64_t aEndTime, |
437 int64_t aEndTime, |
380 int64_t aCurrentTime) |
438 int64_t aCurrentTime) |
381 @@ -514,52 +592,62 @@ nsresult GStreamerReader::Seek(int64_t a |
439 @@ -514,52 +610,62 @@ nsresult GStreamerReader::Seek(int64_t a |
382 |
440 |
383 nsresult GStreamerReader::GetBuffered(nsTimeRanges* aBuffered, |
441 nsresult GStreamerReader::GetBuffered(nsTimeRanges* aBuffered, |
384 int64_t aStartTime) |
442 int64_t aStartTime) |
385 { |
443 { |
386 if (!mInfo.mHasVideo && !mInfo.mHasAudio) { |
444 if (!mInfo.mHasVideo && !mInfo.mHasAudio) { |
442 LOG(PR_LOG_DEBUG, ("adding range [%f, %f] for [%li %li] size %li", |
500 LOG(PR_LOG_DEBUG, ("adding range [%f, %f] for [%li %li] size %li", |
443 start, end, startOffset, endOffset, resourceLength)); |
501 start, end, startOffset, endOffset, resourceLength)); |
444 aBuffered->Add(start, end); |
502 aBuffered->Add(start, end); |
445 } |
503 } |
446 |
504 |
447 @@ -568,48 +656,64 @@ nsresult GStreamerReader::GetBuffered(ns |
505 @@ -568,48 +674,64 @@ nsresult GStreamerReader::GetBuffered(ns |
448 |
506 |
449 void GStreamerReader::ReadAndPushData(guint aLength) |
507 void GStreamerReader::ReadAndPushData(guint aLength) |
450 { |
508 { |
451 MediaResource* resource = mDecoder->GetResource(); |
509 MediaResource* resource = mDecoder->GetResource(); |
452 NS_ASSERTION(resource, "Decoder has no media resource"); |
510 NS_ASSERTION(resource, "Decoder has no media resource"); |
508 duration = GST_TIME_AS_USECONDS (duration); |
566 duration = GST_TIME_AS_USECONDS (duration); |
509 } |
567 } |
510 } |
568 } |
511 |
569 |
512 /*if (mDecoder->mDuration != -1 && |
570 /*if (mDecoder->mDuration != -1 && |
513 @@ -673,60 +777,95 @@ gboolean GStreamerReader::SeekData(GstAp |
571 @@ -673,60 +795,95 @@ gboolean GStreamerReader::SeekData(GstAp |
514 if (NS_SUCCEEDED(rv)) |
572 if (NS_SUCCEEDED(rv)) |
515 mByteOffset = mLastReportedByteOffset = aOffset; |
573 mByteOffset = mLastReportedByteOffset = aOffset; |
516 else |
574 else |
517 LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset)); |
575 LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset)); |
518 |
576 |
604 gpointer aUserData) |
662 gpointer aUserData) |
605 { |
663 { |
606 GStreamerReader *reader = (GStreamerReader *) aUserData; |
664 GStreamerReader *reader = (GStreamerReader *) aUserData; |
607 |
665 |
608 if (aSink == reader->mVideoAppSink) |
666 if (aSink == reader->mVideoAppSink) |
609 @@ -735,18 +874,22 @@ GstFlowReturn GStreamerReader::NewPrerol |
667 @@ -735,18 +892,22 @@ GstFlowReturn GStreamerReader::NewPrerol |
610 reader->AudioPreroll(); |
668 reader->AudioPreroll(); |
611 return GST_FLOW_OK; |
669 return GST_FLOW_OK; |
612 } |
670 } |
613 |
671 |
614 void GStreamerReader::AudioPreroll() |
672 void GStreamerReader::AudioPreroll() |
628 gst_structure_get_int(s, "channels", (gint *) &mInfo.mAudioChannels); |
686 gst_structure_get_int(s, "channels", (gint *) &mInfo.mAudioChannels); |
629 NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero")); |
687 NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero")); |
630 NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero")); |
688 NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero")); |
631 NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS, |
689 NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS, |
632 "invalid audio channels number"); |
690 "invalid audio channels number"); |
633 @@ -754,19 +897,29 @@ void GStreamerReader::AudioPreroll() |
691 @@ -754,19 +915,29 @@ void GStreamerReader::AudioPreroll() |
634 gst_caps_unref(caps); |
692 gst_caps_unref(caps); |
635 gst_object_unref(sinkpad); |
693 gst_object_unref(sinkpad); |
636 } |
694 } |
637 |
695 |
638 void GStreamerReader::VideoPreroll() |
696 void GStreamerReader::VideoPreroll() |