Changeset 154683 in webkit
- Timestamp:
- Aug 27, 2013 8:00:07 AM (11 years ago)
- Location:
- trunk/Source
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r154655 r154683 1 2013-08-27 Andre Moreira Magalhaes <andre.magalhaes@collabora.co.uk> 2 3 [gstreamer] Make sure gstreamer source element is thread-safe 4 https://bugs.webkit.org/show_bug.cgi?id=115352 5 6 Reviewed by Philippe Normand. 7 8 Add convenience class that simplifies locking and unlocking a GMutex. 9 10 * GNUmakefile.list.am: 11 * wtf/gobject/GMutexLocker.h: Added. 12 (WebCore::GMutexLocker::GMutexLocker): 13 (WebCore::GMutexLocker::~GMutexLocker): 14 (WebCore::GMutexLocker::lock): 15 (WebCore::GMutexLocker::unlock): 16 (WebCore::GMutexLocker::mutex): 17 1 18 2013-08-26 Andy Estes <aestes@apple.com> 2 19 -
trunk/Source/WTF/GNUmakefile.list.am
r154498 r154683 214 214 Source/WTF/wtf/dtoa/strtod.h \ 215 215 Source/WTF/wtf/dtoa/utils.h \ 216 Source/WTF/wtf/gobject/GMutexLocker.h \ 216 217 Source/WTF/wtf/gobject/GOwnPtr.cpp \ 217 218 Source/WTF/wtf/gobject/GOwnPtr.h \ -
trunk/Source/WebCore/ChangeLog
r154682 r154683 1 2013-08-27 Andre Moreira Magalhaes <andre.magalhaes@collabora.co.uk> 2 3 [gstreamer] Make sure gstreamer source element is thread-safe 4 https://bugs.webkit.org/show_bug.cgi?id=115352 5 6 Reviewed by Philippe Normand. 7 8 GStreamer source element may be created by any gstreamer element on any thread by calling 9 gst_element_make_from_uri with the URIs handled by the source element. 10 This patch makes sure the gstreamer source element is thread-safe to avoid issues with it 11 being created outside the main thread. 12 13 * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp: 14 (webkit_web_src_init): 15 (webKitWebSrcDispose): 16 (webKitWebSrcFinalize): 17 (webKitWebSrcSetProperty): 18 (webKitWebSrcGetProperty): 19 (removeTimeoutSources): 20 (webKitWebSrcStop): 21 (webKitWebSrcStart): 22 (webKitWebSrcChangeState): 23 (webKitWebSrcQueryWithParent): 24 (webKitWebSrcGetUri): 25 (webKitWebSrcSetUri): 26 (webKitWebSrcNeedDataMainCb): 27 (webKitWebSrcNeedDataCb): 28 (webKitWebSrcEnoughDataMainCb): 29 (webKitWebSrcEnoughDataCb): 30 (webKitWebSrcSeekMainCb): 31 (webKitWebSrcSeekDataCb): 32 (webKitWebSrcSetMediaPlayer): 33 (StreamingClient::StreamingClient): 34 (StreamingClient::~StreamingClient): 35 (StreamingClient::createReadBuffer): 36 (StreamingClient::handleResponseReceived): 37 (StreamingClient::handleDataReceived): 38 (StreamingClient::handleNotifyFinished): 39 (CachedResourceStreamingClient::CachedResourceStreamingClient): 40 (CachedResourceStreamingClient::~CachedResourceStreamingClient): 41 (CachedResourceStreamingClient::loadFailed): 42 (CachedResourceStreamingClient::setDefersLoading): 43 (CachedResourceStreamingClient::getOrCreateReadBuffer): 44 (CachedResourceStreamingClient::responseReceived): 45 (CachedResourceStreamingClient::dataReceived): 46 (CachedResourceStreamingClient::notifyFinished): 47 (ResourceHandleStreamingClient::ResourceHandleStreamingClient): 48 (ResourceHandleStreamingClient::~ResourceHandleStreamingClient): 49 (ResourceHandleStreamingClient::loadFailed): 50 (ResourceHandleStreamingClient::setDefersLoading): 51 (ResourceHandleStreamingClient::getOrCreateReadBuffer): 52 (ResourceHandleStreamingClient::willSendRequest): 53 (ResourceHandleStreamingClient::didReceiveResponse): 54 (ResourceHandleStreamingClient::didReceiveData): 55 (ResourceHandleStreamingClient::didFinishLoading): 56 (ResourceHandleStreamingClient::didFail): 57 (ResourceHandleStreamingClient::wasBlocked): 58 (ResourceHandleStreamingClient::cannotShowURL): 59 Make element thread-safe, add support to use the element without a player associated (e.g. 60 the DASH plugin using the webkitsrc to download fragments), use GMutexLocker to simplify 61 locks and other general improvements. 62 1 63 2013-08-27 Antti Koivisto <antti@apple.com> 2 64 -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
r153795 r154683 32 32 #include "MediaPlayer.h" 33 33 #include "NotImplemented.h" 34 #include "ResourceHandle.h" 35 #include "ResourceHandleClient.h" 34 36 #include "ResourceRequest.h" 35 37 #include "ResourceResponse.h" … … 38 40 #include <gst/pbutils/missing-plugins.h> 39 41 #include <wtf/Noncopyable.h> 42 #include <wtf/gobject/GMutexLocker.h> 40 43 #include <wtf/gobject/GOwnPtr.h> 41 44 #include <wtf/gobject/GRefPtr.h> … … 44 47 using namespace WebCore; 45 48 46 class StreamingClient : public CachedRawResourceClient { 47 WTF_MAKE_NONCOPYABLE(StreamingClient); WTF_MAKE_FAST_ALLOCATED; 49 class StreamingClient { 48 50 public: 49 51 StreamingClient(WebKitWebSrc*); 50 52 virtual ~StreamingClient(); 51 53 54 virtual bool loadFailed() const = 0; 55 virtual void setDefersLoading(bool) = 0; 56 57 protected: 58 char* createReadBuffer(size_t requestedSize, size_t& actualSize); 59 void handleResponseReceived(const ResourceResponse&); 60 void handleDataReceived(const char*, int); 61 void handleNotifyFinished(); 62 63 GRefPtr<GstElement> m_src; 64 }; 65 66 class CachedResourceStreamingClient : public CachedRawResourceClient, public StreamingClient { 67 WTF_MAKE_NONCOPYABLE(CachedResourceStreamingClient); WTF_MAKE_FAST_ALLOCATED; 68 public: 69 CachedResourceStreamingClient(WebKitWebSrc*, CachedResourceLoader*, const ResourceRequest&); 70 virtual ~CachedResourceStreamingClient(); 71 72 // StreamingClient virtual methods. 73 virtual bool loadFailed() const; 74 virtual void setDefersLoading(bool); 75 52 76 private: 53 // CachedResourceClient 77 // CachedResourceClient virtual methods. 78 virtual char* getOrCreateReadBuffer(CachedResource*, size_t requestedSize, size_t& actualSize); 54 79 virtual void responseReceived(CachedResource*, const ResourceResponse&); 55 80 virtual void dataReceived(CachedResource*, const char*, int); 56 81 virtual void notifyFinished(CachedResource*); 57 virtual char* getOrCreateReadBuffer(CachedResource*, size_t requestedSize, size_t& actualSize); 58 59 WebKitWebSrc* m_src; 82 83 CachedResourceHandle<CachedRawResource> m_resource; 84 }; 85 86 class ResourceHandleStreamingClient : public ResourceHandleClient, public StreamingClient { 87 WTF_MAKE_NONCOPYABLE(ResourceHandleStreamingClient); WTF_MAKE_FAST_ALLOCATED; 88 public: 89 ResourceHandleStreamingClient(WebKitWebSrc*, const ResourceRequest&); 90 virtual ~ResourceHandleStreamingClient(); 91 92 // StreamingClient virtual methods. 93 virtual bool loadFailed() const; 94 virtual void setDefersLoading(bool); 95 96 private: 97 // ResourceHandleClient virtual methods. 98 virtual char* getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize); 99 virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&); 100 virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); 101 virtual void didReceiveData(ResourceHandle*, const char*, int, int); 102 virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/); 103 virtual void didFail(ResourceHandle*, const ResourceError&); 104 virtual void wasBlocked(ResourceHandle*); 105 virtual void cannotShowURL(ResourceHandle*); 106 107 RefPtr<ResourceHandle> m_resource; 60 108 }; 61 109 … … 69 117 70 118 StreamingClient* client; 71 CachedResourceHandle<CachedRawResource> resource;72 119 73 120 guint64 offset; … … 78 125 guint64 requestedOffset; 79 126 127 guint startID; 128 guint stopID; 80 129 guint needDataID; 81 130 guint enoughDataID; … … 130 179 static gboolean webKitWebSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer userData); 131 180 132 static void webKitWebSrcStop(WebKitWebSrc*, bool);133 134 181 static GstAppSrcCallbacks appsrcCallbacks = { 135 182 webKitWebSrcNeedDataCb, … … 185 232 0, 186 233 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); 187 234 188 235 g_object_class_install_property(oklass, 189 236 PROP_IRADIO_URL, … … 222 269 223 270 src->priv = priv; 224 225 priv->client = new StreamingClient(src);226 271 227 272 priv->appsrc = GST_APP_SRC(gst_element_factory_make("appsrc", 0)); … … 273 318 g_object_set(priv->appsrc, "min-percent", 20, NULL); 274 319 275 webKitWebSrcStop(src, false); 320 gst_app_src_set_caps(priv->appsrc, 0); 321 gst_app_src_set_size(priv->appsrc, -1); 276 322 } 277 323 … … 281 327 WebKitWebSrcPrivate* priv = src->priv; 282 328 283 if (priv->buffer) {284 #ifdef GST_API_VERSION_1285 unmapGstBuffer(priv->buffer.get());286 #endif287 priv->buffer.clear();288 }289 290 329 priv->player = 0; 291 330 … … 298 337 WebKitWebSrcPrivate* priv = src->priv; 299 338 300 delete priv->client;301 302 339 g_free(priv->uri); 303 340 … … 311 348 312 349 switch (propID) { 313 case PROP_IRADIO_MODE: 350 case PROP_IRADIO_MODE: { 351 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 314 352 priv->iradioMode = g_value_get_boolean(value); 315 353 break; 354 } 316 355 case PROP_LOCATION: 317 356 #ifdef GST_API_VERSION_1 … … 332 371 WebKitWebSrcPrivate* priv = src->priv; 333 372 373 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 334 374 switch (propID) { 335 375 case PROP_IRADIO_MODE: … … 357 397 } 358 398 359 360 static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking) 361 { 362 WebKitWebSrcPrivate* priv = src->priv; 363 364 if (priv->resource) { 365 priv->resource->removeClient(priv->client); 366 priv->resource = 0; 367 } 399 static void removeTimeoutSources(WebKitWebSrc* src) 400 { 401 WebKitWebSrcPrivate* priv = src->priv; 402 403 if (priv->startID) 404 g_source_remove(priv->startID); 405 priv->startID = 0; 406 407 if (priv->needDataID) 408 g_source_remove(priv->needDataID); 409 priv->needDataID = 0; 410 411 if (priv->enoughDataID) 412 g_source_remove(priv->enoughDataID); 413 priv->enoughDataID = 0; 414 415 if (priv->seekID) 416 g_source_remove(priv->seekID); 417 priv->seekID = 0; 418 } 419 420 static gboolean webKitWebSrcStop(WebKitWebSrc* src) 421 { 422 WebKitWebSrcPrivate* priv = src->priv; 423 424 ASSERT(isMainThread()); 425 426 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 427 428 bool seeking = priv->seekID; 429 430 removeTimeoutSources(src); 431 priv->stopID = 0; 368 432 369 433 if (priv->client) { … … 379 443 } 380 444 381 GST_OBJECT_LOCK(src);382 if (priv->needDataID)383 g_source_remove(priv->needDataID);384 priv->needDataID = 0;385 386 if (priv->enoughDataID)387 g_source_remove(priv->enoughDataID);388 priv->enoughDataID = 0;389 390 if (priv->seekID)391 g_source_remove(priv->seekID);392 priv->seekID = 0;393 394 445 priv->paused = FALSE; 395 GST_OBJECT_UNLOCK(src);396 446 397 447 g_free(priv->iradioName); … … 406 456 g_free(priv->iradioTitle); 407 457 priv->iradioTitle = 0; 458 459 priv->offset = 0; 460 priv->seekable = FALSE; 461 462 if (!seeking) { 463 priv->size = 0; 464 priv->requestedOffset = 0; 465 priv->player = 0; 466 } 467 468 locker.unlock(); 408 469 409 470 if (priv->appsrc) { … … 413 474 } 414 475 415 priv->offset = 0;416 priv->seekable = FALSE;417 418 if (!seeking) {419 priv->size = 0;420 priv->requestedOffset = 0;421 }422 423 476 GST_DEBUG_OBJECT(src, "Stopped request"); 424 } 425 426 static bool webKitWebSrcStart(WebKitWebSrc* src) 427 { 428 WebKitWebSrcPrivate* priv = src->priv; 477 478 return FALSE; 479 } 480 481 static gboolean webKitWebSrcStart(WebKitWebSrc* src) 482 { 483 WebKitWebSrcPrivate* priv = src->priv; 484 485 ASSERT(isMainThread()); 486 487 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 488 489 priv->startID = 0; 429 490 430 491 if (!priv->uri) { 431 492 GST_ERROR_OBJECT(src, "No URI provided"); 432 return false; 433 } 434 435 ASSERT(priv->player); 493 locker.unlock(); 494 webKitWebSrcStop(src); 495 return FALSE; 496 } 497 498 ASSERT(!priv->client); 436 499 437 500 KURL url = KURL(KURL(), priv->uri); … … 439 502 ResourceRequest request(url); 440 503 request.setAllowCookies(true); 441 request.setHTTPReferrer(priv->player->referrer()); 504 505 if (priv->player) 506 request.setHTTPReferrer(priv->player->referrer()); 442 507 443 508 #if USE(SOUP) … … 470 535 request.setHTTPHeaderField("transferMode.dlna", "Streaming"); 471 536 472 if (CachedResourceLoader* loader = priv->player->cachedResourceLoader()) { 473 CachedResourceRequest cacheRequest(request, ResourceLoaderOptions(SendCallbacks, DoNotSniffContent, DoNotBufferData, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType)); 474 priv->resource = loader->requestRawResource(cacheRequest); 475 if (priv->resource) { 476 priv->client = new StreamingClient(src); 477 priv->resource->addClient(priv->client); 537 if (priv->player) { 538 if (CachedResourceLoader* loader = priv->player->cachedResourceLoader()) 539 priv->client = new CachedResourceStreamingClient(src, loader, request); 540 } 541 542 if (!priv->client) 543 priv->client = new ResourceHandleStreamingClient(src, request); 544 545 if (!priv->client || priv->client->loadFailed()) { 546 GST_ERROR_OBJECT(src, "Failed to setup streaming client"); 547 if (priv->client) { 548 delete priv->client; 549 priv->client = 0; 478 550 } 479 } 480 481 if (!priv->resource) { 482 GST_ERROR_OBJECT(src, "Failed to schedule resource load"); 483 return false; 484 } 485 551 locker.unlock(); 552 webKitWebSrcStop(src); 553 return FALSE; 554 } 486 555 GST_DEBUG_OBJECT(src, "Started request"); 487 488 return true; 556 return FALSE; 489 557 } 490 558 … … 514 582 } 515 583 584 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 516 585 switch (transition) { 517 586 case GST_STATE_CHANGE_READY_TO_PAUSED: 518 587 GST_DEBUG_OBJECT(src, "READY->PAUSED"); 519 if (!webKitWebSrcStart(src)) 520 ret = GST_STATE_CHANGE_FAILURE; 588 priv->startID = g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc) webKitWebSrcStart, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 521 589 break; 522 590 case GST_STATE_CHANGE_PAUSED_TO_READY: 523 591 GST_DEBUG_OBJECT(src, "PAUSED->READY"); 524 webKitWebSrcStop(src, false); 592 // cancel pending sources 593 removeTimeoutSources(src); 594 priv->stopID = g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc) webKitWebSrcStop, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 525 595 break; 526 596 default: … … 533 603 static gboolean webKitWebSrcQueryWithParent(GstPad* pad, GstObject* parent, GstQuery* query) 534 604 { 535 WebKitWebSrc* webkitSrc = WEBKIT_WEB_SRC(GST_ELEMENT(parent));605 WebKitWebSrc* src = WEBKIT_WEB_SRC(GST_ELEMENT(parent)); 536 606 gboolean result = FALSE; 537 607 … … 542 612 gst_query_parse_duration(query, &format, NULL); 543 613 544 GST_DEBUG_OBJECT(webkitSrc, "duration query in format %s", gst_format_get_name(format)); 545 if ((format == GST_FORMAT_BYTES) && (webkitSrc->priv->size > 0)) { 546 gst_query_set_duration(query, format, webkitSrc->priv->size); 614 GST_DEBUG_OBJECT(src, "duration query in format %s", gst_format_get_name(format)); 615 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 616 if (format == GST_FORMAT_BYTES && src->priv->size > 0) { 617 gst_query_set_duration(query, format, src->priv->size); 547 618 result = TRUE; 548 619 } … … 550 621 } 551 622 case GST_QUERY_URI: { 552 gst_query_set_uri(query, webkitSrc->priv->uri); 623 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 624 gst_query_set_uri(query, src->priv->uri); 553 625 result = TRUE; 554 626 break; … … 591 663 static gchar* webKitWebSrcGetUri(GstURIHandler* handler) 592 664 { 593 return g_strdup(WEBKIT_WEB_SRC(handler)->priv->uri); 665 WebKitWebSrc* src = WEBKIT_WEB_SRC(handler); 666 gchar* ret; 667 668 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 669 ret = g_strdup(src->priv->uri); 670 return ret; 594 671 } 595 672 … … 604 681 } 605 682 683 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 684 606 685 g_free(priv->uri); 607 686 priv->uri = 0; … … 635 714 static const gchar* webKitWebSrcGetUri(GstURIHandler* handler) 636 715 { 637 return g_strdup(WEBKIT_WEB_SRC(handler)->priv->uri); 716 WebKitWebSrc* src = WEBKIT_WEB_SRC(handler); 717 gchar* ret; 718 719 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 720 ret = g_strdup(src->priv->uri); 721 return ret; 638 722 } 639 723 … … 647 731 return FALSE; 648 732 } 733 734 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 649 735 650 736 g_free(priv->uri); … … 682 768 WebKitWebSrcPrivate* priv = src->priv; 683 769 684 priv->resource->setDefersLoading(false); 685 686 GST_OBJECT_LOCK(src); 770 ASSERT(isMainThread()); 771 772 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 773 // already stopped 774 if (!priv->needDataID) 775 return FALSE; 776 687 777 priv->paused = FALSE; 688 778 priv->needDataID = 0; 689 GST_OBJECT_UNLOCK(src); 779 locker.unlock(); 780 781 if (priv->client) 782 priv->client->setDefersLoading(false); 690 783 return FALSE; 691 784 } … … 698 791 GST_DEBUG_OBJECT(src, "Need more data: %u", length); 699 792 700 G ST_OBJECT_LOCK(src);793 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 701 794 if (priv->needDataID || !priv->paused) { 702 GST_OBJECT_UNLOCK(src);703 795 return; 704 796 } 705 797 706 priv->needDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 707 GST_OBJECT_UNLOCK(src); 798 priv->needDataID = g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 708 799 } 709 800 … … 712 803 WebKitWebSrcPrivate* priv = src->priv; 713 804 714 priv->resource->setDefersLoading(true); 715 716 GST_OBJECT_LOCK(src); 805 ASSERT(isMainThread()); 806 807 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 808 // already stopped 809 if (!priv->enoughDataID) 810 return FALSE; 811 717 812 priv->paused = TRUE; 718 813 priv->enoughDataID = 0; 719 GST_OBJECT_UNLOCK(src); 720 814 locker.unlock(); 815 816 if (priv->client) 817 priv->client->setDefersLoading(true); 721 818 return FALSE; 722 819 } … … 729 826 GST_DEBUG_OBJECT(src, "Have enough data"); 730 827 731 G ST_OBJECT_LOCK(src);828 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 732 829 if (priv->enoughDataID || priv->paused) { 733 GST_OBJECT_UNLOCK(src);734 830 return; 735 831 } 736 832 737 priv->enoughDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 738 GST_OBJECT_UNLOCK(src); 833 priv->enoughDataID = g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 739 834 } 740 835 741 836 static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src) 742 837 { 743 webKitWebSrcStop(src, true); 838 WebKitWebSrcPrivate* priv = src->priv; 839 840 ASSERT(isMainThread()); 841 842 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 843 // already stopped 844 if (!priv->seekID) 845 return FALSE; 846 locker.unlock(); 847 848 webKitWebSrcStop(src); 744 849 webKitWebSrcStart(src); 745 850 … … 753 858 754 859 GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, offset); 860 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 755 861 if (offset == priv->offset && priv->requestedOffset == priv->offset) 756 862 return TRUE; … … 762 868 priv->requestedOffset = offset; 763 869 764 GST_OBJECT_LOCK(src);765 870 if (priv->seekID) 766 871 g_source_remove(priv->seekID); 767 priv->seekID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 768 GST_OBJECT_UNLOCK(src); 769 872 priv->seekID = g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); 770 873 return TRUE; 771 874 } … … 774 877 { 775 878 ASSERT(player); 879 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 776 880 src->priv->player = player; 777 881 } 778 882 779 StreamingClient::StreamingClient(WebKitWebSrc* src) : m_src(src)780 { 781 883 StreamingClient::StreamingClient(WebKitWebSrc* src) 884 : m_src(adoptGRef(static_cast<GstElement*>(gst_object_ref(src)))) 885 { 782 886 } 783 887 784 888 StreamingClient::~StreamingClient() 785 889 { 786 787 } 788 789 void StreamingClient::responseReceived(CachedResource* resource, const ResourceResponse& response) 790 { 791 WebKitWebSrcPrivate* priv = m_src->priv; 792 793 GST_DEBUG_OBJECT(m_src, "Received response: %d", response.httpStatusCode()); 890 } 891 892 char* StreamingClient::createReadBuffer(size_t requestedSize, size_t& actualSize) 893 { 894 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 895 WebKitWebSrcPrivate* priv = src->priv; 896 897 ASSERT(!priv->buffer); 898 899 GstBuffer* buffer = gst_buffer_new_and_alloc(requestedSize); 900 901 #ifdef GST_API_VERSION_1 902 mapGstBuffer(buffer); 903 #endif 904 905 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 906 priv->buffer = adoptGRef(buffer); 907 locker.unlock(); 908 909 actualSize = getGstBufferSize(buffer); 910 return getGstBufferDataPointer(buffer); 911 } 912 913 void StreamingClient::handleResponseReceived(const ResourceResponse& response) 914 { 915 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 916 WebKitWebSrcPrivate* priv = src->priv; 917 918 GST_DEBUG_OBJECT(src, "Received response: %d", response.httpStatusCode()); 919 920 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 794 921 795 922 // If we seeked we need 206 == PARTIAL_CONTENT 796 923 if (priv->requestedOffset && response.httpStatusCode() != 206) { 797 GST_ELEMENT_ERROR(m_src, RESOURCE, READ, (0), (0)); 924 locker.unlock(); 925 GST_ELEMENT_ERROR(src, RESOURCE, READ, (0), (0)); 798 926 gst_app_src_end_of_stream(priv->appsrc); 799 webKitWebSrcStop( m_src, false);927 webKitWebSrcStop(src); 800 928 return; 801 929 } 802 930 803 931 long long length = response.expectedContentLength(); 804 if (length > 0) {932 if (length > 0) 805 933 length += priv->requestedOffset; 806 gst_app_src_set_size(priv->appsrc, length);807 808 #ifndef GST_API_VERSION_1809 if (!priv->haveAppSrc27) {810 gst_segment_set_duration(&GST_BASE_SRC(priv->appsrc)->segment, GST_FORMAT_BYTES, length);811 gst_element_post_message(GST_ELEMENT(priv->appsrc),812 gst_message_new_duration(GST_OBJECT(priv->appsrc),813 GST_FORMAT_BYTES, length));814 }815 #endif816 }817 934 818 935 priv->size = length >= 0 ? length : 0; 819 936 priv->seekable = length > 0 && g_ascii_strcasecmp("none", response.httpHeaderField("Accept-Ranges").utf8().data()); 820 821 // icecast stuff822 String value = response.httpHeaderField("icy-metaint");823 if (!value.isEmpty()) {824 gchar* endptr = 0;825 gint64 icyMetaInt = g_ascii_strtoll(value.utf8().data(), &endptr, 10);826 827 if (endptr && *endptr == '\0' && icyMetaInt > 0) {828 GRefPtr<GstCaps> caps = adoptGRef(gst_caps_new_simple("application/x-icy", "metadata-interval", G_TYPE_INT, (gint) icyMetaInt, NULL));829 830 gst_app_src_set_caps(priv->appsrc, caps.get());831 }832 }833 937 834 938 #ifdef GST_API_VERSION_1 … … 837 941 GstTagList* tags = gst_tag_list_new(); 838 942 #endif 839 value = response.httpHeaderField("icy-name");943 String value = response.httpHeaderField("icy-name"); 840 944 if (!value.isEmpty()) { 841 945 g_free(priv->iradioName); 842 946 priv->iradioName = g_strdup(value.utf8().data()); 843 g_object_notify(G_OBJECT( m_src), "iradio-name");947 g_object_notify(G_OBJECT(src), "iradio-name"); 844 948 gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_ORGANIZATION, priv->iradioName, NULL); 845 949 } … … 848 952 g_free(priv->iradioGenre); 849 953 priv->iradioGenre = g_strdup(value.utf8().data()); 850 g_object_notify(G_OBJECT( m_src), "iradio-genre");954 g_object_notify(G_OBJECT(src), "iradio-genre"); 851 955 gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE, priv->iradioGenre, NULL); 852 956 } … … 855 959 g_free(priv->iradioUrl); 856 960 priv->iradioUrl = g_strdup(value.utf8().data()); 857 g_object_notify(G_OBJECT( m_src), "iradio-url");961 g_object_notify(G_OBJECT(src), "iradio-url"); 858 962 gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_LOCATION, priv->iradioUrl, NULL); 859 963 } … … 862 966 g_free(priv->iradioTitle); 863 967 priv->iradioTitle = g_strdup(value.utf8().data()); 864 g_object_notify(G_OBJECT( m_src), "iradio-title");968 g_object_notify(G_OBJECT(src), "iradio-title"); 865 969 gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, priv->iradioTitle, NULL); 866 970 } 867 971 972 locker.unlock(); 973 974 // notify size/duration 975 if (length > 0) { 976 gst_app_src_set_size(priv->appsrc, length); 977 978 #ifndef GST_API_VERSION_1 979 if (!priv->haveAppSrc27) { 980 gst_segment_set_duration(&GST_BASE_SRC(priv->appsrc)->segment, GST_FORMAT_BYTES, length); 981 gst_element_post_message(GST_ELEMENT(priv->appsrc), 982 gst_message_new_duration(GST_OBJECT(priv->appsrc), 983 GST_FORMAT_BYTES, length)); 984 } 985 #endif 986 } else 987 gst_app_src_set_size(priv->appsrc, -1); 988 989 // icecast stuff 990 value = response.httpHeaderField("icy-metaint"); 991 if (!value.isEmpty()) { 992 gchar* endptr = 0; 993 gint64 icyMetaInt = g_ascii_strtoll(value.utf8().data(), &endptr, 10); 994 995 if (endptr && *endptr == '\0' && icyMetaInt > 0) { 996 GRefPtr<GstCaps> caps = adoptGRef(gst_caps_new_simple("application/x-icy", "metadata-interval", G_TYPE_INT, (gint) icyMetaInt, NULL)); 997 998 gst_app_src_set_caps(priv->appsrc, caps.get()); 999 } 1000 } else 1001 gst_app_src_set_caps(priv->appsrc, 0); 1002 1003 // notify tags 868 1004 if (gst_tag_list_is_empty(tags)) 869 1005 #ifdef GST_API_VERSION_1 … … 873 1009 #endif 874 1010 else 875 notifyGstTagsOnPad(GST_ELEMENT(m_src), m_src->priv->srcpad, tags); 876 } 877 878 void StreamingClient::dataReceived(CachedResource* resource, const char* data, int length) 879 { 880 WebKitWebSrcPrivate* priv = m_src->priv; 881 882 GST_LOG_OBJECT(m_src, "Have %d bytes of data", priv->buffer ? getGstBufferSize(priv->buffer.get()) : length); 1011 notifyGstTagsOnPad(GST_ELEMENT(src), priv->srcpad, tags); 1012 } 1013 1014 void StreamingClient::handleDataReceived(const char* data, int length) 1015 { 1016 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1017 WebKitWebSrcPrivate* priv = src->priv; 1018 1019 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 1020 1021 GST_LOG_OBJECT(src, "Have %d bytes of data", priv->buffer ? getGstBufferSize(priv->buffer.get()) : length); 883 1022 884 1023 ASSERT(!priv->buffer || data == getGstBufferDataPointer(priv->buffer.get())); … … 889 1028 #endif 890 1029 891 if (priv->seekID || resource != priv->resource) {892 GST_DEBUG_OBJECT( m_src, "Seek in progress, ignoring data");1030 if (priv->seekID) { 1031 GST_DEBUG_OBJECT(src, "Seek in progress, ignoring data"); 893 1032 priv->buffer.clear(); 894 1033 return; … … 908 1047 // priv->size == 0 if received length on didReceiveResponse < 0. 909 1048 if (priv->size > 0 && priv->offset > priv->size) { 910 GST_DEBUG_OBJECT( m_src, "Updating internal size from %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT, priv->size, priv->offset);1049 GST_DEBUG_OBJECT(src, "Updating internal size from %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT, priv->size, priv->offset); 911 1050 gst_app_src_set_size(priv->appsrc, priv->offset); 912 1051 priv->size = priv->offset; 913 1052 } 914 1053 GST_BUFFER_OFFSET_END(priv->buffer.get()) = priv->offset; 1054 1055 locker.unlock(); 915 1056 916 1057 GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, priv->buffer.leakRef()); … … 920 1061 if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED) 921 1062 #endif 922 GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0)); 923 } 924 925 char* StreamingClient::getOrCreateReadBuffer(CachedResource*, size_t requestedSize, size_t& actualSize) 926 { 927 WebKitWebSrcPrivate* priv = m_src->priv; 928 929 ASSERT(!priv->buffer); 930 931 GstBuffer* buffer = gst_buffer_new_and_alloc(requestedSize); 932 933 #ifdef GST_API_VERSION_1 934 mapGstBuffer(buffer); 935 #endif 936 937 priv->buffer = adoptGRef(buffer); 938 939 actualSize = getGstBufferSize(buffer); 940 return getGstBufferDataPointer(buffer); 941 } 942 943 void StreamingClient::notifyFinished(CachedResource* resource) 944 { 945 WebKitWebSrcPrivate* priv = m_src->priv; 946 1063 GST_ELEMENT_ERROR(src, CORE, FAILED, (0), (0)); 1064 } 1065 1066 void StreamingClient::handleNotifyFinished() 1067 { 1068 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1069 WebKitWebSrcPrivate* priv = src->priv; 1070 1071 GST_DEBUG_OBJECT(src, "Have EOS"); 1072 1073 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 1074 if (!priv->seekID) { 1075 locker.unlock(); 1076 gst_app_src_end_of_stream(priv->appsrc); 1077 } 1078 } 1079 1080 CachedResourceStreamingClient::CachedResourceStreamingClient(WebKitWebSrc* src, CachedResourceLoader* resourceLoader, const ResourceRequest& request) 1081 : StreamingClient(src) 1082 { 1083 CachedResourceRequest cacheRequest(request, ResourceLoaderOptions(SendCallbacks, DoNotSniffContent, DoNotBufferData, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType)); 1084 m_resource = resourceLoader->requestRawResource(cacheRequest); 1085 if (m_resource) 1086 m_resource->addClient(this); 1087 } 1088 1089 CachedResourceStreamingClient::~CachedResourceStreamingClient() 1090 { 1091 if (m_resource) { 1092 m_resource->removeClient(this); 1093 m_resource = 0; 1094 } 1095 } 1096 1097 bool CachedResourceStreamingClient::loadFailed() const 1098 { 1099 return !m_resource; 1100 } 1101 1102 void CachedResourceStreamingClient::setDefersLoading(bool defers) 1103 { 1104 if (m_resource) 1105 m_resource->setDefersLoading(defers); 1106 } 1107 1108 char* CachedResourceStreamingClient::getOrCreateReadBuffer(CachedResource*, size_t requestedSize, size_t& actualSize) 1109 { 1110 return createReadBuffer(requestedSize, actualSize); 1111 } 1112 1113 void CachedResourceStreamingClient::responseReceived(CachedResource*, const ResourceResponse& response) 1114 { 1115 handleResponseReceived(response); 1116 } 1117 1118 void CachedResourceStreamingClient::dataReceived(CachedResource*, const char* data, int length) 1119 { 1120 handleDataReceived(data, length); 1121 } 1122 1123 void CachedResourceStreamingClient::notifyFinished(CachedResource* resource) 1124 { 947 1125 if (resource->loadFailedOrCanceled()) { 1126 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1127 948 1128 if (!resource->wasCanceled()) { 949 1129 const ResourceError& error = resource->resourceError(); 950 GST_ERROR_OBJECT( m_src, "Have failure: %s", error.localizedDescription().utf8().data());951 GST_ELEMENT_ERROR( m_src, RESOURCE, FAILED, ("%s", error.localizedDescription().utf8().data()), (0));1130 GST_ERROR_OBJECT(src, "Have failure: %s", error.localizedDescription().utf8().data()); 1131 GST_ELEMENT_ERROR(src, RESOURCE, FAILED, ("%s", error.localizedDescription().utf8().data()), (0)); 952 1132 } 953 gst_app_src_end_of_stream( m_src->priv->appsrc);1133 gst_app_src_end_of_stream(src->priv->appsrc); 954 1134 return; 955 1135 } 956 1136 957 GST_DEBUG_OBJECT(m_src, "Have EOS"); 958 959 if (!priv->seekID) 960 gst_app_src_end_of_stream(m_src->priv->appsrc); 1137 handleNotifyFinished(); 1138 } 1139 1140 ResourceHandleStreamingClient::ResourceHandleStreamingClient(WebKitWebSrc* src, const ResourceRequest& request) 1141 : StreamingClient(src) 1142 { 1143 m_resource = ResourceHandle::create(0 /*context*/, request, this, false, false); 1144 } 1145 1146 ResourceHandleStreamingClient::~ResourceHandleStreamingClient() 1147 { 1148 if (m_resource) { 1149 m_resource->cancel(); 1150 m_resource.release(); 1151 m_resource = 0; 1152 } 1153 } 1154 1155 bool ResourceHandleStreamingClient::loadFailed() const 1156 { 1157 return !m_resource; 1158 } 1159 1160 void ResourceHandleStreamingClient::setDefersLoading(bool defers) 1161 { 1162 if (m_resource) 1163 m_resource->setDefersLoading(defers); 1164 } 1165 1166 char* ResourceHandleStreamingClient::getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize) 1167 { 1168 return createReadBuffer(requestedSize, actualSize); 1169 } 1170 1171 void ResourceHandleStreamingClient::willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&) 1172 { 1173 } 1174 1175 void ResourceHandleStreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) 1176 { 1177 handleResponseReceived(response); 1178 } 1179 1180 void ResourceHandleStreamingClient::didReceiveData(ResourceHandle*, const char* data, int length, int) 1181 { 1182 handleDataReceived(data, length); 1183 } 1184 1185 void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*, double) 1186 { 1187 handleNotifyFinished(); 1188 } 1189 1190 void ResourceHandleStreamingClient::didFail(ResourceHandle*, const ResourceError& error) 1191 { 1192 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1193 1194 GST_ERROR_OBJECT(src, "Have failure: %s", error.localizedDescription().utf8().data()); 1195 GST_ELEMENT_ERROR(src, RESOURCE, FAILED, ("%s", error.localizedDescription().utf8().data()), (0)); 1196 gst_app_src_end_of_stream(src->priv->appsrc); 1197 } 1198 1199 void ResourceHandleStreamingClient::wasBlocked(ResourceHandle*) 1200 { 1201 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1202 GOwnPtr<gchar> uri; 1203 1204 GST_ERROR_OBJECT(src, "Request was blocked"); 1205 1206 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 1207 uri.set(g_strdup(src->priv->uri)); 1208 locker.unlock(); 1209 1210 GST_ELEMENT_ERROR(src, RESOURCE, OPEN_READ, ("Access to \"%s\" was blocked", uri.get()), (0)); 1211 } 1212 1213 void ResourceHandleStreamingClient::cannotShowURL(ResourceHandle*) 1214 { 1215 WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get()); 1216 GOwnPtr<gchar> uri; 1217 1218 GST_ERROR_OBJECT(src, "Cannot show URL"); 1219 1220 GMutexLocker locker(GST_OBJECT_GET_LOCK(src)); 1221 uri.set(g_strdup(src->priv->uri)); 1222 locker.unlock(); 1223 1224 GST_ELEMENT_ERROR(src, RESOURCE, OPEN_READ, ("Can't show \"%s\"", uri.get()), (0)); 961 1225 } 962 1226
Note: See TracChangeset
for help on using the changeset viewer.