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.