Changeset 247010 in webkit
- Timestamp:
- Jul 1, 2019 9:57:03 AM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r246951 r247010 1 2019-07-01 Philippe Normand <pnormand@igalia.com> 2 3 [GStreamer] Cannot play Bert's Bytes radio stream from http://radio.dos.nl/ 4 https://bugs.webkit.org/show_bug.cgi?id=198376 5 6 Reviewed by Xabier Rodriguez-Calvar. 7 8 * wtf/glib/GLibUtilities.h: 9 (enumToString): Utility function to get a string representation of of a GLib enum. 10 1 11 2019-06-22 Darin Adler <darin@apple.com> 2 12 -
trunk/Source/WTF/wtf/glib/GLibUtilities.cpp
r237099 r247010 78 78 return g_get_prgname(); 79 79 } 80 81 CString enumToString(GType type, guint value) 82 { 83 #if GLIB_CHECK_VERSION(2, 54, 0) 84 GUniquePtr<char> result(g_enum_to_string(type, value)); 85 return result.get(); 86 #else 87 GEnumClass* enumClass = reinterpret_cast<GEnumClass*>(g_type_class_ref(type)); 88 GEnumValue* enumValue = g_enum_get_value(enumClass, value); 89 char* representation = enumValue ? g_strdup(enumValue->value_nick) : nullptr; 90 g_type_class_unref(enumClass); 91 GUniquePtr<char> result(representation); 92 return result.get(); 93 #endif 94 } -
trunk/Source/WTF/wtf/glib/GLibUtilities.h
r228987 r247010 21 21 #define GLibUtilities_h 22 22 23 #include <glib-object.h> 23 24 #include <wtf/Assertions.h> 24 25 #include <wtf/text/CString.h> … … 26 27 CString getCurrentExecutablePath(); 27 28 CString getCurrentExecutableName(); 29 CString enumToString(GType, guint value); 28 30 29 31 // These might be added to glib in the future, but in the meantime they're defined here. -
trunk/Source/WebCore/ChangeLog
r247007 r247010 1 2019-07-01 Philippe Normand <pnormand@igalia.com> 2 3 [GStreamer] Cannot play Bert's Bytes radio stream from http://radio.dos.nl/ 4 https://bugs.webkit.org/show_bug.cgi?id=198376 5 6 Reviewed by Xabier Rodriguez-Calvar. 7 8 The delayed startup was due to a mix of buffering feedback 9 messages not handled correctly by the player. We were handling 10 download and streaming buffering metrics without distinction. 11 Range requests (used for seeking) were also triggering on-disk 12 buffering in some cases. The buffering percentage estimation based 13 on network read position was not working either because uint64_t 14 division doesn't return a floating point value. 15 16 No new tests, existing media tests cover this patch. 17 18 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: 19 (WebCore::MediaPlayerPrivateGStreamer::commitLoad): 20 (WebCore::MediaPlayerPrivateGStreamer::play): 21 (WebCore::MediaPlayerPrivateGStreamer::handleMessage): 22 (WebCore::MediaPlayerPrivateGStreamer::processBufferingStats): 23 (WebCore::MediaPlayerPrivateGStreamer::updateBufferingStatus): 24 (WebCore::MediaPlayerPrivateGStreamer::fillTimerFired): 25 (WebCore::MediaPlayerPrivateGStreamer::maxTimeLoaded const): 26 (WebCore::MediaPlayerPrivateGStreamer::didLoadingProgress const): 27 (WebCore::MediaPlayerPrivateGStreamer::updateStates): 28 (WebCore::MediaPlayerPrivateGStreamer::updateDownloadBufferingFlag): 29 (WebCore::MediaPlayerPrivateGStreamer::setPreload): 30 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: 31 * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp: 32 (webkitWebSrcReset): 33 * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h: 34 1 35 2019-07-01 Miguel Gomez <magomez@igalia.com> 2 36 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
r246730 r247010 49 49 #include <wtf/URL.h> 50 50 #include <wtf/WallTime.h> 51 #include <wtf/glib/G UniquePtr.h>51 #include <wtf/glib/GLibUtilities.h> 52 52 #include <wtf/glib/RunLoopSourcePriority.h> 53 53 #include <wtf/text/CString.h> … … 350 350 changePipelineState(GST_STATE_PAUSED); 351 351 352 setDownloadBuffering();352 updateDownloadBufferingFlag(); 353 353 updateStates(); 354 354 } … … 459 459 m_delayingLoad = false; 460 460 m_preload = MediaPlayer::Auto; 461 setDownloadBuffering();461 updateDownloadBufferingFlag(); 462 462 GST_INFO_OBJECT(pipeline(), "Play"); 463 463 } else … … 1350 1350 } 1351 1351 } 1352 1353 bool isRangeRequest = false; 1354 GUniqueOutPtr<GstStructure> requestHeaders; 1355 if (gst_structure_get(structure, "request-headers", GST_TYPE_STRUCTURE, &requestHeaders.outPtr(), nullptr)) 1356 isRangeRequest = gst_structure_has_field(requestHeaders.get(), "Range"); 1357 1358 GST_DEBUG_OBJECT(pipeline(), "Is range request: %s", boolForPrinting(isRangeRequest)); 1359 1352 1360 GUniqueOutPtr<GstStructure> responseHeaders; 1353 1361 if (gst_structure_get(structure, "response-headers", GST_TYPE_STRUCTURE, &responseHeaders.outPtr(), nullptr)) { … … 1364 1372 } 1365 1373 } 1366 GST_INFO_OBJECT(pipeline(), "%s stream detected", !contentLength ? "Live" : "Non-live");1367 if (!contentLength) {1368 m_isStreaming = true;1369 setDownloadBuffering();1374 if (!isRangeRequest) { 1375 m_isStreaming = !contentLength; 1376 GST_INFO_OBJECT(pipeline(), "%s stream detected", m_isStreaming ? "Live" : "Non-live"); 1377 updateDownloadBufferingFlag(); 1370 1378 } 1371 1379 } … … 1451 1459 void MediaPlayerPrivateGStreamer::processBufferingStats(GstMessage* message) 1452 1460 { 1453 m_buffering = true; 1454 gst_message_parse_buffering(message, &m_bufferingPercentage); 1455 1456 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Buffering: %d%%.", m_bufferingPercentage); 1457 1458 if (m_bufferingPercentage == 100) 1461 GstBufferingMode mode; 1462 gst_message_parse_buffering_stats(message, &mode, nullptr, nullptr, nullptr); 1463 1464 int percentage; 1465 gst_message_parse_buffering(message, &percentage); 1466 1467 updateBufferingStatus(mode, percentage); 1468 } 1469 1470 void MediaPlayerPrivateGStreamer::updateMaxTimeLoaded(double percentage) 1471 { 1472 MediaTime mediaDuration = durationMediaTime(); 1473 if (!mediaDuration) 1474 return; 1475 1476 m_maxTimeLoaded = MediaTime(percentage * static_cast<double>(toGstUnsigned64Time(mediaDuration)) / 100, GST_SECOND); 1477 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Updated maxTimeLoaded: %s", toString(m_maxTimeLoaded).utf8().data()); 1478 } 1479 1480 void MediaPlayerPrivateGStreamer::updateBufferingStatus(GstBufferingMode mode, double percentage) 1481 { 1482 GST_DEBUG_OBJECT(pipeline(), "[Buffering] mode: %s, status: %f%%", enumToString(GST_TYPE_BUFFERING_MODE, mode).data(), percentage); 1483 1484 m_downloadFinished = percentage == 100; 1485 m_buffering = !m_downloadFinished; 1486 1487 switch (mode) { 1488 case GST_BUFFERING_STREAM: { 1489 updateMaxTimeLoaded(percentage); 1490 1491 m_bufferingPercentage = percentage; 1492 if (m_downloadFinished) 1493 updateStates(); 1494 1495 break; 1496 } 1497 case GST_BUFFERING_DOWNLOAD: { 1498 updateMaxTimeLoaded(percentage); 1499 1500 // Media is now fully loaded. It will play even if network connection is 1501 // cut. Buffering is done, remove the fill source from the main loop. 1502 if (m_downloadFinished) 1503 m_fillTimer.stop(); 1504 1459 1505 updateStates(); 1506 break; 1507 } 1508 default: 1509 GST_DEBUG_OBJECT(pipeline(), "Unhandled buffering mode: %s", enumToString(GST_TYPE_BUFFERING_MODE, mode).data()); 1510 break; 1511 } 1460 1512 } 1461 1513 … … 1586 1638 GRefPtr<GstQuery> query = adoptGRef(gst_query_new_buffering(GST_FORMAT_PERCENT)); 1587 1639 double fillStatus = 100.0; 1588 1589 if (gst_element_query(m_pipeline.get(), query.get())) { 1590 int64_t stop; 1591 GstFormat format; 1592 gst_query_parse_buffering_range(query.get(), &format, nullptr, &stop, nullptr); 1593 ASSERT(format == GST_FORMAT_PERCENT); 1594 1595 if (stop != -1) 1596 fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX; 1640 GstBufferingMode mode = GST_BUFFERING_DOWNLOAD; 1641 1642 if (gst_element_query(m_source.get(), query.get())) { 1643 gst_query_parse_buffering_stats(query.get(), &mode, nullptr, nullptr, nullptr); 1644 1645 int percentage; 1646 gst_query_parse_buffering_percent(query.get(), nullptr, &percentage); 1647 fillStatus = percentage; 1597 1648 } else if (m_httpResponseTotalSize) { 1598 1649 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Query failed, falling back to network read position estimation"); 1599 fillStatus = 100.0 * ( m_networkReadPosition / m_httpResponseTotalSize);1650 fillStatus = 100.0 * (static_cast<double>(m_networkReadPosition) / static_cast<double>(m_httpResponseTotalSize)); 1600 1651 } else { 1601 1652 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Unable to determine on-disk buffering status"); … … 1603 1654 } 1604 1655 1605 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Download buffer filled up to %f%%", fillStatus); 1606 1607 MediaTime mediaDuration = durationMediaTime(); 1608 1609 // Update maxTimeLoaded only if the media duration is 1610 // available. Otherwise we can't compute it. 1611 if (mediaDuration) { 1612 if (fillStatus == 100.0) 1613 m_maxTimeLoaded = mediaDuration; 1614 else 1615 m_maxTimeLoaded = MediaTime(fillStatus * static_cast<double>(toGstUnsigned64Time(mediaDuration)) / 100, GST_SECOND); 1616 GST_DEBUG_OBJECT(pipeline(), "[Buffering] Updated maxTimeLoaded: %s", toString(m_maxTimeLoaded).utf8().data()); 1617 } 1618 1619 m_downloadFinished = fillStatus == 100.0; 1620 if (!m_downloadFinished) { 1621 updateStates(); 1622 return; 1623 } 1624 1625 // Media is now fully loaded. It will play even if network 1626 // connection is cut. Buffering is done, remove the fill source 1627 // from the main loop. 1628 m_fillTimer.stop(); 1629 updateStates(); 1656 updateBufferingStatus(mode, fillStatus); 1630 1657 } 1631 1658 … … 1656 1683 if (m_isEndReached) 1657 1684 loaded = durationMediaTime(); 1658 GST_LOG ("maxTimeLoaded: %s", toString(loaded).utf8().data());1685 GST_LOG_OBJECT(pipeline(), "maxTimeLoaded: %s", toString(loaded).utf8().data()); 1659 1686 return loaded; 1660 1687 } … … 1667 1694 if (WEBKIT_IS_WEB_SRC(m_source.get())) { 1668 1695 GST_LOG_OBJECT(pipeline(), "Last network read position: %" G_GUINT64_FORMAT ", current: %" G_GUINT64_FORMAT, m_readPositionAtLastDidLoadingProgress, m_networkReadPosition); 1669 bool didLoadingProgress = m_readPositionAtLastDidLoadingProgress !=m_networkReadPosition;1696 bool didLoadingProgress = m_readPositionAtLastDidLoadingProgress < m_networkReadPosition; 1670 1697 m_readPositionAtLastDidLoadingProgress = m_networkReadPosition; 1698 GST_LOG_OBJECT(pipeline(), "didLoadingProgress: %s", boolForPrinting(didLoadingProgress)); 1671 1699 return didLoadingProgress; 1672 1700 } … … 2002 2030 // Live pipelines go in PAUSED without prerolling. 2003 2031 m_isStreaming = true; 2004 setDownloadBuffering();2032 updateDownloadBufferingFlag(); 2005 2033 2006 2034 if (m_currentState == GST_STATE_READY) … … 2257 2285 } 2258 2286 2259 void MediaPlayerPrivateGStreamer:: setDownloadBuffering()2287 void MediaPlayerPrivateGStreamer::updateDownloadBufferingFlag() 2260 2288 { 2261 2289 if (!m_pipeline) … … 2292 2320 2293 2321 m_preload = preload; 2294 setDownloadBuffering();2322 updateDownloadBufferingFlag(); 2295 2323 2296 2324 if (m_delayingLoad && m_preload != MediaPlayer::None) { -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
r246677 r247010 155 155 void mediaLocationChanged(GstMessage*); 156 156 157 virtual void setDownloadBuffering();157 virtual void updateDownloadBufferingFlag(); 158 158 void processBufferingStats(GstMessage*); 159 void updateBufferingStatus(GstBufferingMode, double percentage); 160 void updateMaxTimeLoaded(double percentage); 161 159 162 #if ENABLE(VIDEO_TRACK) 160 163 #if USE(GSTREAMER_MPEGTS) -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
r246399 r247010 238 238 WebKitWebSrcPrivate* priv = WEBKIT_WEB_SRC_GET_PRIVATE(src); 239 239 240 GST_DEBUG_OBJECT(src, "Resetting internal state"); 240 241 priv->haveSize = false; 241 242 priv->wereHeadersReceived = false; -
trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h
r242034 r247010 53 53 void load(const String&, MediaSourcePrivateClient*) override; 54 54 55 void setDownloadBuffering() override { };55 void updateDownloadBufferingFlag() override { }; 56 56 57 57 bool isLiveStream() const override { return false; }
Note: See TracChangeset
for help on using the changeset viewer.