From 58cedadefe494d55066007b425560d58c420fb8a Mon Sep 17 00:00:00 2001 From: zhx447 Date: Wed, 27 Aug 2025 16:20:50 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=AF=B7=E6=B1=82=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=92=AD=E6=94=BE2=E7=A7=92=E5=86=85=E8=B6=85=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=90=88=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhx447 --- .../network_client/http_curl_client.cpp | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp b/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp index d7f19aa99..b9492246a 100644 --- a/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp +++ b/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp @@ -242,12 +242,6 @@ Status HttpCurlClient::Open(const std::string& url, const std::map 0 ? timeoutMs / MILLS_TO_SECOND : DEFAULT_LOW_SPEED_TIME; - curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_LIMIT, DEFAULT_LOW_SPEED_LIMIT); - curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_TIME, timeout); + ret = curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_LIMIT, DEFAULT_LOW_SPEED_LIMIT); + if (ret != CURLE_OK) { MEDIA_LOG_I("Curl error " PUBLIC_LOG_D32 " " PUBLIC_LOG_S, ret, curl_easy_strerror(ret)); } + ret = curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_TIME, timeout); + if (ret != CURLE_OK) { MEDIA_LOG_I("Curl error " PUBLIC_LOG_D32 " " PUBLIC_LOG_S, ret, curl_easy_strerror(ret)); } InitCurProxy(url); } @@ -395,7 +390,8 @@ Status HttpCurlClient::RequestData(long startPos, int len, const RequestInfo& re MEDIA_LOG_D("RequestData: startPos " PUBLIC_LOG_D32 ", len " PUBLIC_LOG_D32, static_cast(startPos), len); CURLcode returnCode = curl_easy_perform(easyHandle_); if (returnCode != CURLE_OK) { - MEDIA_LOG_E("Curl error " PUBLIC_LOG_D32, returnCode); + MEDIA_LOG_E("RequestData: startPos " PUBLIC_LOG_D32 ", len " PUBLIC_LOG_D32 ". Curl error " PUBLIC_LOG_D32 + " " PUBLIC_LOG_S, static_cast(startPos), len, returnCode, curl_easy_strerror(returnCode)); clientCode = returnCode; ret = Status::ERROR_CLIENT; } else { -- Gitee From 36760ce89b923b1d6cc2d995f79aa0958203791e Mon Sep 17 00:00:00 2001 From: zhx447 Date: Fri, 5 Sep 2025 10:56:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0URI=E4=B8=AD=E5=AF=B9?= =?UTF-8?q?=E5=AF=B9=E4=B9=A6=E7=AD=BE=E6=A0=87=E8=AE=B0=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhx447 --- .../network_client/http_curl_client.cpp | 24 +++++++------ .../source/http_source/http_source_plugin.cpp | 34 ++++++++++++++----- .../http_source_plugin_unit_test.cpp | 6 ++++ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp b/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp index b9492246a..d7f19aa99 100644 --- a/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp +++ b/services/media_engine/plugins/source/http_source/download/network_client/http_curl_client.cpp @@ -242,6 +242,12 @@ Status HttpCurlClient::Open(const std::string& url, const std::map 0 ? timeoutMs / MILLS_TO_SECOND : DEFAULT_LOW_SPEED_TIME; - ret = curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_LIMIT, DEFAULT_LOW_SPEED_LIMIT); - if (ret != CURLE_OK) { MEDIA_LOG_I("Curl error " PUBLIC_LOG_D32 " " PUBLIC_LOG_S, ret, curl_easy_strerror(ret)); } - ret = curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_TIME, timeout); - if (ret != CURLE_OK) { MEDIA_LOG_I("Curl error " PUBLIC_LOG_D32 " " PUBLIC_LOG_S, ret, curl_easy_strerror(ret)); } + curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_LIMIT, DEFAULT_LOW_SPEED_LIMIT); + curl_easy_setopt(easyHandle_, CURLOPT_LOW_SPEED_TIME, timeout); InitCurProxy(url); } @@ -390,8 +395,7 @@ Status HttpCurlClient::RequestData(long startPos, int len, const RequestInfo& re MEDIA_LOG_D("RequestData: startPos " PUBLIC_LOG_D32 ", len " PUBLIC_LOG_D32, static_cast(startPos), len); CURLcode returnCode = curl_easy_perform(easyHandle_); if (returnCode != CURLE_OK) { - MEDIA_LOG_E("RequestData: startPos " PUBLIC_LOG_D32 ", len " PUBLIC_LOG_D32 ". Curl error " PUBLIC_LOG_D32 - " " PUBLIC_LOG_S, static_cast(startPos), len, returnCode, curl_easy_strerror(returnCode)); + MEDIA_LOG_E("Curl error " PUBLIC_LOG_D32, returnCode); clientCode = returnCode; ret = Status::ERROR_CLIENT; } else { diff --git a/services/media_engine/plugins/source/http_source/http_source_plugin.cpp b/services/media_engine/plugins/source/http_source/http_source_plugin.cpp index d4a719c37..4192d9e10 100644 --- a/services/media_engine/plugins/source/http_source/http_source_plugin.cpp +++ b/services/media_engine/plugins/source/http_source/http_source_plugin.cpp @@ -518,6 +518,26 @@ void HttpSourcePlugin::WaitForBufferingEnd() downloader_->WaitForBufferingEnd(); } +static std::pair SplitUri(const std::string& uri) +{ + /* RFC3986 Url可以划分成若干个组件,协议、主机、路径等。有一些字符(:/?#[]@)是用作分隔不同组件的,作为保留字符。 + 例如:冒号用于分隔协议和主机,/用于分隔主机和路径,?用于分隔路径和查询参数,百分号(%)制定特殊字符,#号指定书签, + &号分隔参数。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。*/ + std::string::size_type pos = uri.find_first_of('?'); + if (pos != std::string::npos) { + return std::make_pair(uri.substr(0, pos), uri.substr(pos + 1)); + } + + // #作用是已给纯粹的客户端“锚点”,它不会被发送到客户端。因此#放在?之前的URL不符合规范的。 + // 例如:http://1500005450.vod2.myqcloud.com/playlist_eof.m3u8#maxBufferSize=30000 + pos = uri.find_first_of('#'); + if (pos != std::string::npos) { + return std::make_pair(uri.substr(0, pos), ""); + } + + return std::make_pair(uri, ""); +} + bool HttpSourcePlugin::CheckIsM3U8Uri() { if (uri_.empty()) { @@ -526,25 +546,23 @@ bool HttpSourcePlugin::CheckIsM3U8Uri() std::string uri = uri_; std::transform(uri.begin(), uri.end(), uri.begin(), ::tolower); - std::string::size_type pos = uri.find('?'); - std::string uriMain = (pos != std::string::npos) ? uri.substr(0, pos) : uri; - std::string uriParam = (pos != std::string::npos) ? uri.substr(pos + 1) : ""; - pos = uriMain.rfind('/'); + auto pairUri = SplitUri(uri); + std::string::size_type pos = pairUri.first.rfind('/'); if (pos == std::string::npos) { return false; } // 现网的很多hls链接是非.m3u8关键字,举例:http://xxx/xxxx?autotype=m3u8; http://xxx/aaa.doplaylist?auto=m3u8 - // 优先判断资源类型(.和?中间的字符串,姑且称资源类型);参数携带为次。如果不携带资源类型,还走原来的逻辑 - std::string leafNameSuffix = uriMain.substr(pos + 1); + // 优先判断资源类型(.和?#中间的字符串,姑且称资源类型);参数携带为次。如果不携带资源类型,还走原来的逻辑 + std::string leafNameSuffix = pairUri.first.substr(pos + 1); pos = leafNameSuffix.rfind('.'); if (pos != std::string::npos) { // 找到资源格式 std::string suffix = leafNameSuffix.substr(pos + 1); if (suffix == LOWER_M3U8) { return true; } - if (!uriParam.empty()) { - if (uriParam.find(EQUAL_M3U8) != std::string::npos) { + if (!pairUri.second.empty()) { + if (pairUri.second.find(EQUAL_M3U8) != std::string::npos) { return true; } } diff --git a/test/unittest/http_source_test/http_source_plugin_unit_test.cpp b/test/unittest/http_source_test/http_source_plugin_unit_test.cpp index 35385270b..6647574c1 100644 --- a/test/unittest/http_source_test/http_source_plugin_unit_test.cpp +++ b/test/unittest/http_source_test/http_source_plugin_unit_test.cpp @@ -416,6 +416,12 @@ HWTEST_F(HttpSourcePluginUnitTest, IsSeekToTimeSupported10, TestSize.Level1) EXPECT_TRUE(httpSourcePlugin->IsSeekToTimeSupported()); } +HWTEST_F(HttpSourcePluginUnitTest, IsSeekToTimeSupported11, TestSize.Level1) +{ + httpSourcePlugin->uri_ = "http://1500005450.vod2.myqcloud.com/playlist_eof.m3u8#maxBufferSize=30000"; + EXPECT_TRUE(httpSourcePlugin->IsSeekToTimeSupported()); +} + HWTEST_F(HttpSourcePluginUnitTest, Read_IsNull, TestSize.Level1) { httpSourcePlugin->downloader_ = nullptr; -- Gitee