From 428f79b92e00d2f0f7de6cccbc57fa72f9f473bf Mon Sep 17 00:00:00 2001 From: pingkai Date: Wed, 26 Feb 2020 15:34:23 +0800 Subject: [PATCH] feat(data_source): support open with range Signed-off-by: pingkai --- framework/data_source/IDataSource.cpp | 7 +++++++ framework/data_source/IDataSource.h | 10 ++++++++-- .../data_source/curl/curl_data_source.cpp | 19 +++++++++++++++++-- framework/data_source/ffmpeg_data_source.cpp | 12 ++++++++++++ framework/data_source/proxyDataSource.cpp | 2 +- framework/data_source/proxyDataSource.h | 2 +- 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/framework/data_source/IDataSource.cpp b/framework/data_source/IDataSource.cpp index 3f0395433..7b10024e3 100644 --- a/framework/data_source/IDataSource.cpp +++ b/framework/data_source/IDataSource.cpp @@ -75,6 +75,13 @@ namespace Cicada { return mOpts; } + int IDataSource::setRange(int64_t start, int64_t end) + { + rangeStart = start; + rangeEnd = end; + return 0; + } + std::string IDataSource::SourceConfig::toString() { CicadaJSONItem item{}; diff --git a/framework/data_source/IDataSource.h b/framework/data_source/IDataSource.h index 927b6a80c..595a4fb8b 100644 --- a/framework/data_source/IDataSource.h +++ b/framework/data_source/IDataSource.h @@ -11,7 +11,7 @@ #include #include -namespace Cicada{ +namespace Cicada { enum { SEEK_SIZE = 0x10000, @@ -28,7 +28,9 @@ namespace Cicada{ }; virtual NetWorkRetryStatus onNetWorkRetry(int error) = 0; - virtual void onNetWorkConnected(){ + + virtual void onNetWorkConnected() + { } }; @@ -59,6 +61,8 @@ namespace Cicada{ virtual ~IDataSource() = default; + virtual int setRange(int64_t start, int64_t end); + virtual int Open(int flags) = 0; virtual int Open(const std::string &url); @@ -90,6 +94,8 @@ namespace Cicada{ std::atomic_bool mInterrupt{false}; SourceConfig mConfig{}; std::string mUri{}; + int64_t rangeStart{INT64_MIN}; + int64_t rangeEnd{INT64_MIN}; }; } diff --git a/framework/data_source/curl/curl_data_source.cpp b/framework/data_source/curl/curl_data_source.cpp index 35bd1d43d..08fe18758 100644 --- a/framework/data_source/curl/curl_data_source.cpp +++ b/framework/data_source/curl/curl_data_source.cpp @@ -186,7 +186,7 @@ int CurlDataSource::Open(int flags) mPConnection->setInterrupt(&mInterrupt); } - int ret = curl_connect(mPConnection, 0); + int ret = curl_connect(mPConnection, rangeStart != INT64_MIN ? rangeStart : 0); mOpenTimeMS = af_gettime_relative() / 1000 - mOpenTimeMS; if (ret >= 0) { @@ -203,13 +203,20 @@ int CurlDataSource::Open(const string &url) return Open(0); } + if (mUri == url) { + if (rangeStart != INT64_MIN) { + Seek(rangeStart, SEEK_SET); + return 0; + } + } + mOpenTimeMS = af_gettime_relative() / 1000; mPConnection->disconnect(); bool isRTMP = url.compare(0, 7, "rtmp://") == 0; mLocation = (isRTMP ? (url + " live=1").c_str() : url.c_str()); // only change url, don,t change share and resolve curl_easy_setopt(mPConnection->getCurlHandle(), CURLOPT_URL, mLocation.c_str()); - int ret = curl_connect(mPConnection, 0); + int ret = curl_connect(mPConnection, rangeStart != INT64_MIN ? rangeStart : 0); mOpenTimeMS = af_gettime_relative() / 1000 - mOpenTimeMS; if (ret >= 0) { @@ -360,6 +367,14 @@ int CurlDataSource::Read(void *buf, size_t size) { int ret = 0; + if (rangeEnd != INT64_MIN) { + size = std::min(size, (size_t) (rangeEnd - mPConnection->tell())); + + if (size == 0) { + return 0; + } + } + /* only request 1 byte, for truncated reads (only if not eof) */ if ((mFileSize <= 0 || mPConnection->tell() < mFileSize) && (ret = mPConnection->FillBuffer(1)) < 0) { diff --git a/framework/data_source/ffmpeg_data_source.cpp b/framework/data_source/ffmpeg_data_source.cpp index 16e957a3d..fda307477 100644 --- a/framework/data_source/ffmpeg_data_source.cpp +++ b/framework/data_source/ffmpeg_data_source.cpp @@ -39,6 +39,10 @@ namespace Cicada { ret = FRAMEWORK_ERR_PROTOCOL_NOT_SUPPORT; } + if (rangeStart != INT64_MIN) { + ffurl_seek(mPuc, (int64_t) rangeStart, SEEK_SET); + } + return ret; } @@ -65,6 +69,14 @@ namespace Cicada { int ffmpegDataSource::Read(void *buf, size_t nbyte) { + if (rangeEnd != INT64_MIN) { + nbyte = std::min(nbyte, (size_t) (rangeEnd - Seek(0, SEEK_CUR))); + + if (nbyte == 0) { + return 0; + } + } + int ret = ffurl_read(mPuc, (unsigned char *) buf, nbyte); if (ret == AVERROR_EOF) { diff --git a/framework/data_source/proxyDataSource.cpp b/framework/data_source/proxyDataSource.cpp index c89e4adf7..81b23269d 100644 --- a/framework/data_source/proxyDataSource.cpp +++ b/framework/data_source/proxyDataSource.cpp @@ -24,7 +24,7 @@ namespace Cicada { int proxyDataSource::Open(const string &url) { if (mOpen) { - return mOpen(mUserArg, url.c_str()); + return mOpen(mUserArg, url.c_str(), rangeStart, rangeEnd); } return -1; diff --git a/framework/data_source/proxyDataSource.h b/framework/data_source/proxyDataSource.h index ed0cafa69..cfdde7078 100644 --- a/framework/data_source/proxyDataSource.h +++ b/framework/data_source/proxyDataSource.h @@ -11,7 +11,7 @@ typedef int (*readImpl)(void *arg, uint8_t *buffer, int size); typedef int64_t (*seekImpl)(void *arg, int64_t offset, int whence); -typedef int (*openImpl)(void *arg, const char *url); +typedef int (*openImpl)(void *arg, const char *url,int64_t start, int64_t end); typedef void (*interruptImpl)(void *arg, int inter);