一篇不错的gstream的component开发代码

原创 2008年05月09日 15:27:00

http://publicsvn.songbirdnest.com/browser/trunk/components/mediacore/playback/gstreamer/src/sbGStreamerSimple.cpp?rev=2484

 

root/trunk/components/mediacore/playback/gstreamer/src/sbGStreamerSimple.cpp

Revision 2484, 16.3 kB (checked in by ben, 2 years ago)

Updating line ending restrictions

  • Property svn:eol-style set to LF
Line  
1 #include "sbGStreamerSimple.h"
2 #include "nsIInterfaceRequestorUtils.h"
3  
4 #include "nsIWebNavigation.h"
5 #include "nsIDOMDocument.h"
6 #include "nsIDOMDocumentView.h"
7 #include "nsIDOMXULElement.h"
8 #include "nsIDOMAbstractView.h"
9 #include "nsIDocShellTreeItem.h"
10 #include "nsIDocShellTreeOwner.h"
11 #include "nsIDOMEventTarget.h"
12 #include "nsIDOMEvent.h"
13 #include "nsIDOMEventListener.h"
14 #include "nsIDOMWindow.h"
15 #include "nsIDocument.h"
16 #include "nsIScriptGlobalObject.h"
17 #include "nsIBaseWindow.h"
18 #include "nsIWidget.h"
19 #include "nsIBoxObject.h"
20 #include "nsString.h"
21 #include "prlog.h"
22  
23 #if defined( PR_LOGGING )
24 extern PRLogModuleInfo* gGStreamerLog;
25 #define LOG(args) PR_LOG(gGStreamerLog, PR_LOG_DEBUG, args)
26 #else
27 #define LOG(args)
28 #endif
29  
30 NS_IMPL_ISUPPORTS2(sbGStreamerSimple, sbIGStreamerSimple, nsIDOMEventListener)
31  
32 static GstBusSyncReply
33 syncHandlerHelper(GstBus* bus, GstMessage* message, gpointer data)
34 {
35   sbGStreamerSimple* gsts = NS_STATIC_CAST(sbGStreamerSimple*, data);
36   return gsts->SyncHandler(bus, message);
37 }
38  
39 static void
40 streamInfoSetHelper(GObject* obj, GParamSpec* pspec, sbGStreamerSimple* gsts)
41 {
42   gsts->StreamInfoSet(obj, pspec);
43 }
44  
45 static void
46 capsSetHelper(GObject* obj, GParamSpec* pspec, sbGStreamerSimple* gsts)
47 {
48   gsts->CapsSet(obj, pspec);
49 }
50  
51 sbGStreamerSimple::sbGStreamerSimple() :
52   mInitialized(PR_FALSE),
53   mPlay(NULL),
54   mBus(NULL),
55   mPixelAspectRatioN(1),
56   mPixelAspectRatioD(1),
57   mVideoSink(NULL),
58   mGdkWin(NULL),
59   mIsAtEndOfStream(PR_TRUE),
60   mLastErrorCode(0),
61   mVideoOutputElement(nsnull),
62   mDomWindow(nsnull)
63 {
64   mArtist.Assign(EmptyString());
65   mAlbum.Assign(EmptyString());
66   mTitle.Assign(EmptyString());
67   mGenre.Assign(EmptyString());
68 }
69  
70 sbGStreamerSimple::~sbGStreamerSimple()
71 {
72   if(mPlay != NULL && GST_IS_ELEMENT(mPlay)) {
73     gst_element_set_state(mPlay, GST_STATE_NULL);
74     gst_object_unref(mPlay);
75     mPlay = NULL;
76   }
77  
78   // Do i need to close the video window?
79  
80   mDomWindow = nsnull;
81   mVideoOutputElement = nsnull;
82 }
83  
84 NS_IMETHODIMP
85 sbGStreamerSimple::Init(nsIDOMXULElement* aVideoOutput)
86 {
87   nsresult rv;
88  
89   if(mInitialized) {
90     return NS_OK;
91   }
92  
93   if(aVideoOutput == nsnull) {
94     return NS_ERROR_INVALID_ARG;
95   }
96  
97   mVideoOutputElement = aVideoOutput;
98  
99   // Get a handle to the xul element's native window
100   nsCOMPtr<nsIDOMDocument> domDocument;
101   rv = aVideoOutput->GetOwnerDocument(getter_AddRefs(domDocument));
102   NS_ENSURE_SUCCESS(rv, rv);
103  
104   nsCOMPtr<nsIDOMDocumentView> domDocumentView(do_QueryInterface(domDocument));
105   NS_ENSURE_TRUE(domDocumentView, NS_NOINTERFACE);
106  
107   nsCOMPtr<nsIDOMAbstractView> domAbstractView;
108   rv = domDocumentView->GetDefaultView(getter_AddRefs(domAbstractView));
109   NS_ENSURE_SUCCESS(rv, rv);
110  
111   nsCOMPtr<nsIWebNavigation> webNavigation(do_GetInterface(domAbstractView));
112   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(webNavigation));
113   NS_ENSURE_TRUE(docShellTreeItem, NS_NOINTERFACE);
114  
115   nsCOMPtr<nsIDocShellTreeOwner> docShellTreeOwner;
116   rv = docShellTreeItem->GetTreeOwner(getter_AddRefs(docShellTreeOwner));
117   NS_ENSURE_SUCCESS(rv, rv);
118  
119   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(docShellTreeOwner);
120   NS_ENSURE_TRUE(baseWindow, NS_NOINTERFACE);
121  
122   nsCOMPtr<nsIWidget> widget;
123   rv = baseWindow->GetMainWidget(getter_AddRefs(widget));
124   NS_ENSURE_SUCCESS(rv, rv);
125  
126   // Attach event listeners
127   nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
128   NS_ENSURE_TRUE(document, NS_NOINTERFACE);
129  
130   mDomWindow = do_QueryInterface(document->GetScriptGlobalObject());
131   NS_ENSURE_TRUE(mDomWindow, NS_NOINTERFACE);
132  
133   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDomWindow));
134   NS_ENSURE_TRUE(target, NS_NOINTERFACE);
135   target->AddEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
136   target->AddEventListener(NS_LITERAL_STRING("unload"), this, PR_FALSE);
137  
138   GdkWindow* win = GDK_WINDOW(widget->GetNativeData(NS_NATIVE_WIDGET));
139  
140   LOG(("Found native window %x", win));
141  
142   // Create the video window
143   GdkWindowAttr attributes;
144  
145   attributes.window_type = GDK_WINDOW_CHILD;
146   attributes.x = 0;
147   attributes.y = 0;
148   attributes.width = 0;
149   attributes.height = 0;
150   attributes.wclass = GDK_INPUT_OUTPUT;
151   attributes.event_mask = 0;
152  
153   mGdkWin = gdk_window_new(win, &attributes, GDK_WA_X | GDK_WA_Y);
154   gdk_window_show(mGdkWin);
155   // Set up the playbin
156   mPlay = gst_element_factory_make("playbin", "play");
157   GstElement *audioSink = gst_element_factory_make("gconfaudiosink", "audio-sink");
158   g_object_set(mPlay, "audio-sink", audioSink, NULL);
159  
160   // TODO: use gconf video config here?
161   mVideoSink = gst_element_factory_make("ximagesink", "video-sink");
162   g_object_set(mPlay, "video-sink", mVideoSink, NULL);
163  
164   mBus = gst_element_get_bus(mPlay);
165   gst_bus_set_sync_handler(mBus, &syncHandlerHelper, this);
166  
167   // This signal lets us get info about the stream
168   g_signal_connect(mPlay, "notify::stream-info",
169     G_CALLBACK(streamInfoSetHelper), this);
170  
171   mInitialized = PR_TRUE;
172  
173   return NS_OK;
174 }
175  
176 NS_IMETHODIMP
177 sbGStreamerSimple::GetUri(nsAString& aUri)
178 {
179   if(!mInitialized) {
180     return NS_ERROR_NOT_INITIALIZED;
181   }
182  
183   GValue value = { 0, };
184   g_value_init(&value, G_TYPE_STRING);
185   g_object_get_property(G_OBJECT(mPlay), "uri", &value);
186  
187   nsCAutoString uri;
188   uri.Assign(g_value_get_string(&value));
189  
190   g_value_unset(&value);
191  
192   CopyUTF8toUTF16(uri, aUri);
193  
194   return NS_OK;
195 }
196 NS_IMETHODIMP
197 sbGStreamerSimple::SetUri(const nsAString& aUri)
198 {
199   if(!mInitialized) {
200     return NS_ERROR_NOT_INITIALIZED;
201   }
202  
203   // XXX: What are these glib strings?
204   g_object_set(G_OBJECT(mPlay), "uri", NS_ConvertUTF16toUTF8(aUri).get(), NULL);
205  
206   mArtist.Assign(EmptyString());
207   mAlbum.Assign(EmptyString());
208   mTitle.Assign(EmptyString());
209   mGenre.Assign(EmptyString());
210  
211   return NS_OK;
212 }
213  
214 NS_IMETHODIMP
215 sbGStreamerSimple::GetVolume(double* aVolume)
216 {
217   if(!mInitialized) {
218     return NS_ERROR_NOT_INITIALIZED;
219   }
220  
221   g_object_get(G_OBJECT(mPlay), "volume", aVolume, NULL);
222  
223   return NS_OK;
224 }
225  
226 NS_IMETHODIMP
227 sbGStreamerSimple::SetVolume(double aVolume)
228 {
229   if(!mInitialized) {
230     return NS_ERROR_NOT_INITIALIZED;
231   }
232  
233   g_object_set(mPlay, "volume", aVolume, NULL);
234  
235   return NS_OK;
236 }
237  
238 NS_IMETHODIMP
239 sbGStreamerSimple::GetPosition(PRUint64* aPosition)
240 {
241   if(!mInitialized) {
242     return NS_ERROR_NOT_INITIALIZED;
243   }
244  
245   nsresult rv;
246  
247   GstQuery *query;
248   gboolean res;
249   query = gst_query_new_position(GST_FORMAT_TIME);
250   res = gst_element_query(mPlay, query);
251   if(res) {
252     gint64 position;
253     gst_query_parse_position(query, NULL, &position);
254     *aPosition = position;
255     rv = NS_OK;
256   }
257   else {
258     rv = NS_ERROR_NOT_AVAILABLE;
259   }
260  
261   gst_query_unref (query);
262  
263   return rv;
264 }
265  
266 NS_IMETHODIMP
267 sbGStreamerSimple::GetIsPlaying(PRBool* aIsPlaying)
268 {
269   if(!mInitialized) {
270     return NS_ERROR_NOT_INITIALIZED;
271   }
272  
273   GstState cur, pending;
274  
275   gst_element_get_state(mPlay, &cur, &pending, 0);
276  
277   if(cur == GST_STATE_PLAYING || pending == GST_STATE_PLAYING) {
278     *aIsPlaying = PR_TRUE;
279   }
280   else {
281     *aIsPlaying = PR_FALSE;
282   }
283  
284   return NS_OK;
285 }
286  
287 NS_IMETHODIMP
288 sbGStreamerSimple::GetIsPaused(PRBool* aIsPaused)
289 {
290   if(!mInitialized) {
291     return NS_ERROR_NOT_INITIALIZED;
292   }
293  
294   GstState cur, pending;
295  
296   gst_element_get_state(mPlay, &cur, &pending, 0);
297  
298   if(cur == GST_STATE_PAUSED || pending == GST_STATE_PAUSED) {
299     *aIsPaused = PR_TRUE;
300   }
301   else {
302     *aIsPaused = PR_FALSE;
303   }
304  
305   return NS_OK;
306 }
307  
308 NS_IMETHODIMP
309 sbGStreamerSimple::GetStreamLength(PRUint64* aStreamLength)
310 {
311   if(!mInitialized) {
312     return NS_ERROR_NOT_INITIALIZED;
313   }
314  
315   nsresult rv;
316  
317   GstQuery *query;
318   gboolean res;
319   query = gst_query_new_duration(GST_FORMAT_TIME);
320   res = gst_element_query(mPlay, query);
321   if(res) {
322     gint64 duration;
323     gst_query_parse_duration(query, NULL, &duration);
324     *aStreamLength = duration;
325     rv = NS_OK;
326   }
327   else {
328     rv = NS_ERROR_NOT_AVAILABLE;
329   }
330  
331   gst_query_unref (query);
332  
333   return rv;
334 }
335  
336 NS_IMETHODIMP
337 sbGStreamerSimple::GetIsAtEndOfStream(PRBool* aIsAtEndOfStream)
338 {
339   if(!mInitialized) {
340     return NS_ERROR_NOT_INITIALIZED;
341   }
342  
343   *aIsAtEndOfStream = mIsAtEndOfStream;
344  
345   return NS_OK;
346 }
347  
348 NS_IMETHODIMP
349 sbGStreamerSimple::GetLastErrorCode(PRInt32* aLastErrorCode)
350 {
351   if(!mInitialized) {
352     return NS_ERROR_NOT_INITIALIZED;
353   }
354  
355   *aLastErrorCode = mLastErrorCode;
356  
357   return NS_OK;
358 }
359  
360 NS_IMETHODIMP
361 sbGStreamerSimple::GetArtist(nsAString& aArtist)
362 {
363   if(!mInitialized) {
364     return NS_ERROR_NOT_INITIALIZED;
365   }
366  
367   aArtist.Assign(mArtist);
368  
369   return NS_OK;
370 }
371  
372 NS_IMETHODIMP
373 sbGStreamerSimple::GetAlbum(nsAString& aAlbum)
374 {
375   if(!mInitialized) {
376     return NS_ERROR_NOT_INITIALIZED;
377   }
378  
379   aAlbum.Assign(mAlbum);
380  
381   return NS_OK;
382 }
383  
384 NS_IMETHODIMP
385 sbGStreamerSimple::GetTitle(nsAString& aTitle)
386 {
387   if(!mInitialized) {
388     return NS_ERROR_NOT_INITIALIZED;
389   }
390  
391   aTitle.Assign(mTitle);
392  
393   return NS_OK;
394 }
395  
396 NS_IMETHODIMP
397 sbGStreamerSimple::GetGenre(nsAString& aGenre)
398 {
399   if(!mInitialized) {
400     return NS_ERROR_NOT_INITIALIZED;
401   }
402  
403   aGenre.Assign(mGenre);
404  
405   return NS_OK;
406 }
407  
408 NS_IMETHODIMP
409 sbGStreamerSimple::Play()
410 {
411   if(!mInitialized) {
412     return NS_ERROR_NOT_INITIALIZED;
413   }
414  
415   gst_element_set_state(mPlay, GST_STATE_PLAYING);
416   mIsAtEndOfStream = PR_FALSE;
417   mLastErrorCode = 0;
418  
419   return NS_OK;
420 }
421  
422 NS_IMETHODIMP
423 sbGStreamerSimple::Pause()
424 {
425   if(!mInitialized) {
426     return NS_ERROR_NOT_INITIALIZED;
427   }
428  
429   gst_element_set_state(mPlay, GST_STATE_PAUSED);
430  
431   return NS_OK;
432 }
433  
434 NS_IMETHODIMP
435 sbGStreamerSimple::Stop()
436 {
437   if(!mInitialized) {
438     return NS_ERROR_NOT_INITIALIZED;
439   }
440  
441   gst_element_set_state(mPlay, GST_STATE_NULL);
442  
443   return NS_OK;
444 }
445  
446 NS_IMETHODIMP
447 sbGStreamerSimple::Seek(PRUint64 aTimeNanos)
448 {
449   if(!mInitialized) {
450     return NS_ERROR_NOT_INITIALIZED;
451   }
452  
453   gst_element_seek(mPlay, 1.0,
454       GST_FORMAT_TIME,
455       GstSeekFlags(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
456       GST_SEEK_TYPE_SET, aTimeNanos,
457       GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
458  
459   return NS_OK;
460 }
461  
462 // nsIDOMEventListener
463 NS_IMETHODIMP
464 sbGStreamerSimple::HandleEvent(nsIDOMEvent* aEvent)
465 {
466   nsAutoString eventType;
467   aEvent->GetType(eventType);
468  
469   if(eventType.EqualsLiteral("unload")) {
470  
471     // Clean up here
472     nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDomWindow));
473     NS_ENSURE_TRUE(target, NS_NOINTERFACE);
474     target->RemoveEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
475     target->RemoveEventListener(NS_LITERAL_STRING("unload"), this, PR_FALSE);
476  
477     mDomWindow = nsnull;
478     mVideoOutputElement = nsnull;
479  
480     mInitialized = PR_FALSE;
481  
482     return NS_OK;
483   }
484   else {
485     return Resize();
486   }
487  
488 }
489  
490 NS_IMETHODIMP
491 sbGStreamerSimple::Resize()
492 {
493   PRInt32 x, y, width, height;
494   nsCOMPtr<nsIBoxObject> boxObject;
495   mVideoOutputElement->GetBoxObject(getter_AddRefs(boxObject));
496   boxObject->GetX(&x);
497   boxObject->GetY(&y);
498   boxObject->GetWidth(&width);
499   boxObject->GetHeight(&height);
500  
501   PRInt32 newX, newY, newWidth, newHeight;
502  
503   if(mVideoWidth > 0 && mVideoHeight > 0) {
504  
505     float ratioWidth  = (float) width  / (float) mVideoWidth;
506     float ratioHeight = (float) height / (float) mVideoHeight;
507     if(ratioWidth < ratioHeight) {
508       newWidth  = PRInt32(mVideoWidth  * ratioWidth);
509       newHeight = PRInt32(mVideoHeight * ratioWidth);
510       newX = x;
511       newY = ((height - newHeight) / 2) + y;
512     }
513     else {
514       newWidth  = PRInt32(mVideoWidth  * ratioHeight);
515       newHeight = PRInt32(mVideoHeight * ratioHeight);
516       newX = ((width - newWidth) / 2) + x;
517       newY = y;
518     }
519  
520     gdk_window_move_resize(mGdkWin, newX, newY, newWidth, newHeight);
521   }
522  
523   return NS_OK;
524 }
525  
526 // Callbacks
527 GstBusSyncReply
528 sbGStreamerSimple::SyncHandler(GstBus* bus, GstMessage* message)
529 {
530   GstMessageType msg_type;
531   msg_type = GST_MESSAGE_TYPE(message);
532  
533   switch (msg_type) {
534     case GST_MESSAGE_ERROR: {
535       GError *error = NULL;
536       gchar *debug = NULL;
537  
538       gst_message_parse_error(message, &error, &debug);
539  
540       LOG(("Error message: %s [%s]", GST_STR_NULL (error->message), GST_STR_NULL (debug)));
541  
542       g_free (debug);
543  
544       mLastErrorCode = error->code;
545       mIsAtEndOfStream = PR_TRUE;
546  
547       break;
548     }
549     case GST_MESSAGE_WARNING: {
550       GError *error = NULL;
551       gchar *debug = NULL;
552  
553       gst_message_parse_warning(message, &error, &debug);
554  
555       LOG(("Warning message: %s [%s]", GST_STR_NULL (error->message), GST_STR_NULL (debug)));
556  
557       g_warning ("%s [%s]", GST_STR_NULL (error->message), GST_STR_NULL (debug));
558  
559       g_error_free (error);
560       g_free (debug);
561       break;
562     }
563  
564     case GST_MESSAGE_EOS: {
565       mIsAtEndOfStream = PR_TRUE;
566       break;
567     }
568  
569     case GST_MESSAGE_STATE_CHANGED: {
570       GstState old_state, new_state;
571       gchar *src_name;
572  
573       gst_message_parse_state_changed(message, &old_state, &new_state, NULL);
574  
575       src_name = gst_object_get_name(message->src);
576       LOG(("stage-changed: %s changed state from %s to %s", src_name,
577           gst_element_state_get_name (old_state),
578           gst_element_state_get_name (new_state)));
579       g_free (src_name);
580       break;
581     }
582  
583     case GST_MESSAGE_ELEMENT: {
584       if(gst_structure_has_name(message->structure, "prepare-xwindow-id") && mVideoSink != NULL) {
585         GstElement *element = NULL;
586         GstXOverlay *xoverlay = NULL;
587  
588         if (GST_IS_BIN (mVideoSink)) {
589           element = gst_bin_get_by_interface (GST_BIN (mVideoSink),
590                                               GST_TYPE_X_OVERLAY);
591         }
592         else {
593           element = mVideoSink;
594         }
595  
596         if (GST_IS_X_OVERLAY (element)) {
597           xoverlay = GST_X_OVERLAY (element);
598         }
599         else {
600           xoverlay = NULL;
601         }
602  
603         XID window = GDK_WINDOW_XWINDOW(mGdkWin);
604         gst_x_overlay_set_xwindow_id(xoverlay, window);
605         LOG(("Set xoverlay %d to windowid %d/n", xoverlay, window));
606       }
607       break;
608     }
609  
610     case GST_MESSAGE_TAG: {
611       GstTagList *tag_list;
612       gchar *value = NULL;
613       nsCAutoString temp;
614  
615       gst_message_parse_tag(message, &tag_list);
616  
617       if(gst_tag_list_get_string(tag_list, GST_TAG_ARTIST, &value)) {
618         temp.Assign(value);
619         mArtist.Assign(NS_ConvertUTF8toUTF16(temp).get());
620         g_free(value);
621       }
622  
623       if(gst_tag_list_get_string(tag_list, GST_TAG_ALBUM, &value)) {
624         temp.Assign(value);
625         mAlbum.Assign(NS_ConvertUTF8toUTF16(temp).get());
626         g_free(value);
627       }
628  
629       if(gst_tag_list_get_string(tag_list, GST_TAG_TITLE, &value)) {
630         temp.Assign(value);
631         mTitle.Assign(NS_ConvertUTF8toUTF16(temp).get());
632         g_free(value);
633       }
634  
635       if(gst_tag_list_get_string(tag_list, GST_TAG_GENRE, &value)) {
636         temp.Assign(value);
637         mGenre.Assign(NS_ConvertUTF8toUTF16(temp).get());
638         g_free(value);
639       }
640  
641       gst_tag_list_free(tag_list);
642       break;
643     }
644  
645     default:
646       LOG(("Got message: %s", gst_message_type_get_name(msg_type)));
647   }
648  
649   //gst_message_unref(message); XXX: Do i need to unref this?
650  
651   return GST_BUS_PASS;
652 }
653  
654 void
655 sbGStreamerSimple::StreamInfoSet(GObject* obj, GParamSpec* pspec)
656 {
657   GList *streaminfo = NULL;
658   GstPad *videopad = NULL;
659  
660   g_object_get (mPlay, "stream-info", &streaminfo, NULL);
661   streaminfo = g_list_copy(streaminfo);
662   g_list_foreach (streaminfo, (GFunc) g_object_ref, NULL);
663   for( ; streaminfo != NULL; streaminfo = streaminfo->next) {
664     GObject *info = (GObject*) streaminfo->data;
665     gint type;
666     GParamSpec *pspec;
667     GEnumValue *val;
668  
669     if(!info) {
670       continue;
671     }
672  
673     g_object_get (info, "type", &type, NULL);
674     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info), "type");
675     val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
676  
677     if(!g_strcasecmp (val->value_nick, "video")) {
678       if (!videopad) {
679         g_object_get(info, "object", &videopad, NULL);
680       }
681     }
682   }
683  
684   if(videopad) {
685     GstCaps *caps;
686  
687     if((caps = gst_pad_get_negotiated_caps(videopad))) {
688       CapsSet(G_OBJECT(videopad), NULL);
689       gst_caps_unref(caps);
690     }
691     g_signal_connect(videopad, "notify::caps", G_CALLBACK(capsSetHelper), this);
692   }
693  
694   g_list_foreach (streaminfo, (GFunc) g_object_unref, NULL);
695   g_list_free (streaminfo);
696 }
697  
698 void
699 sbGStreamerSimple::CapsSet(GObject* obj, GParamSpec* pspec)
700 {
701   GstPad *pad = GST_PAD(obj);
702   GstStructure *s;
703   GstCaps *caps;
704  
705   if(!(caps = gst_pad_get_negotiated_caps(pad))) {
706     return;
707   }
708  
709   s = gst_caps_get_structure(caps, 0);
710   if(s) {
711     gst_structure_get_int(s, "width", &mVideoWidth);
712     gst_structure_get_int(s, "height", &mVideoHeight);
713  
714     const GValue* par = gst_structure_get_value(s, "pixel-aspect-ratio");
715     mPixelAspectRatioN = gst_value_get_fraction_numerator(par);
716     mPixelAspectRatioD = gst_value_get_fraction_denominator(par);
717  
718     Resize();
719   }
720  
721   gst_caps_unref(caps);
722 }
723  
Note: See TracBrowser for help on using the browser.

© 2005-2008 POTI, Inc. Mozilla and Firefox are registered trademarks of the Mozilla Foundation.


相关文章推荐

一篇不错的Android Audio架构代码梳理总结

一篇不错的Android Audio架构代码梳理总结 2014-08-22 14:03:41 分类: LINUX    为android系统添加USB A...

剑侠情缘(网络版)---开发回顾(一篇老文章,看看也不错)

剑侠情缘(网络版)---开发回顾                                      ------赵青 文章要点:   ■ 国内的游戏开发团队都需要烧一些浮躁,都一些踏实...

转一篇介绍开发嵌入式经验的文章,写得不错,比较中肯,适合一看。

如何从零开始开发一款嵌入式产品(20年的嵌入式经验)     来源:www.armjishu.com 作者:jesse 转载请注明出处       首先,如果你有幸看到这篇文章,千万不要试图在...
  • yanxuex
  • yanxuex
  • 2013年11月28日 18:08
  • 524

:angularjs学习总结(~~很详细的教程) 很不错的一篇帖子 适合快速了解angularjs整体结构 有个整体印象

1 前言 前端技术的发展是如此之快,各种优秀技术、优秀框架的出现简直让人目不暇接,紧跟时代潮流,学习掌握新知识自然是不敢怠慢。 AngularJS是google在维护,其在国外已经十分火热...

聊天机器人的一篇不错的文章

  • 2016年09月19日 15:20
  • 11.05MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一篇不错的gstream的component开发代码
举报原因:
原因补充:

(最多只允许输入30个字)