mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-28 21:14:03 +08:00
HLS TS 切片下载失败后清除该切片遗留的解复用输入缓存 (#4786)
在 HLS TS 切片下载失败后清除该切片遗留的解复用输入缓存,防止其与下一切片拼接导致错误的包或者损坏的包出现.
This commit is contained in:
@@ -153,6 +153,7 @@ void HlsPlayer::fetchSegment() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
|
strong_self->onSegmentDownloadFailed(err);
|
||||||
WarnL << "Download ts segment " << url << " failed:" << err;
|
WarnL << "Download ts segment " << url << " failed:" << err;
|
||||||
if (err.getErrCode() == Err_timeout) {
|
if (err.getErrCode() == Err_timeout) {
|
||||||
strong_self->_timeout_multiple = MAX(strong_self->_timeout_multiple + 1, MAX_TIMEOUT_MULTIPLE);
|
strong_self->_timeout_multiple = MAX(strong_self->_timeout_multiple + 1, MAX_TIMEOUT_MULTIPLE);
|
||||||
@@ -492,6 +493,14 @@ void HlsPlayerImp::onPacket(const char *data, size_t len) {
|
|||||||
_recvtotalbytes += HlsPlayer::getRecvTotalBytes();
|
_recvtotalbytes += HlsPlayer::getRecvTotalBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HlsPlayerImp::onSegmentDownloadFailed(const toolkit::SockException &ex) {
|
||||||
|
if (_decoder && ex) {
|
||||||
|
// 失败切片的输入残片不能与下一切片拼接;这里只清输入缓存,不 flush 解码帧。
|
||||||
|
// Input left by a failed segment must not join the next one; clear it without flushing decoded frames.
|
||||||
|
_decoder->clearInputCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HlsPlayerImp::addTrackCompleted() {
|
void HlsPlayerImp::addTrackCompleted() {
|
||||||
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(SockException(Err_success, "play hls success"));
|
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(SockException(Err_success, "play hls success"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ protected:
|
|||||||
* [AUTO-TRANSLATED:159a6559]
|
* [AUTO-TRANSLATED:159a6559]
|
||||||
*/
|
*/
|
||||||
virtual void onPacket(const char *data, size_t len) = 0;
|
virtual void onPacket(const char *data, size_t len) = 0;
|
||||||
|
// TS 切片下载失败通知;派生类可清理该切片遗留的输入状态。
|
||||||
|
// Notify derived classes to clear input state left by a failed TS segment.
|
||||||
|
virtual void onSegmentDownloadFailed(const toolkit::SockException &ex) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool onParsed(bool is_m3u8_inner, int64_t sequence, const map<int, ts_segment> &ts_map) override;
|
bool onParsed(bool is_m3u8_inner, int64_t sequence, const map<int, ts_segment> &ts_map) override;
|
||||||
@@ -149,6 +152,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
//// HlsPlayer override////
|
//// HlsPlayer override////
|
||||||
void onPacket(const char *data, size_t len) override;
|
void onPacket(const char *data, size_t len) override;
|
||||||
|
void onSegmentDownloadFailed(const toolkit::SockException &ex) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//// PlayerBase override////
|
//// PlayerBase override////
|
||||||
|
|||||||
@@ -72,6 +72,10 @@ ssize_t DecoderImp::input(const uint8_t *data, size_t bytes){
|
|||||||
return _decoder->input(data, bytes);
|
return _decoder->input(data, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecoderImp::clearInputCache() {
|
||||||
|
_decoder->clearInputCache();
|
||||||
|
}
|
||||||
|
|
||||||
DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){
|
DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){
|
||||||
_decoder = decoder;
|
_decoder = decoder;
|
||||||
_sink = sink;
|
_sink = sink;
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ public:
|
|||||||
using onStream = std::function<void(int stream, int codecid, const void *extra, size_t bytes, int finish)>;
|
using onStream = std::function<void(int stream, int codecid, const void *extra, size_t bytes, int finish)>;
|
||||||
|
|
||||||
virtual ssize_t input(const uint8_t *data, size_t bytes) = 0;
|
virtual ssize_t input(const uint8_t *data, size_t bytes) = 0;
|
||||||
|
// 清理未完成的输入缓存,但不 flush 已解析的帧。
|
||||||
|
// Clear incomplete input cache without flushing parsed frames.
|
||||||
|
virtual void clearInputCache() {}
|
||||||
void setOnDecode(onDecode cb);
|
void setOnDecode(onDecode cb);
|
||||||
void setOnStream(onStream cb);
|
void setOnStream(onStream cb);
|
||||||
|
|
||||||
@@ -45,6 +48,7 @@ public:
|
|||||||
|
|
||||||
static Ptr createDecoder(Type type, MediaSinkInterface *sink);
|
static Ptr createDecoder(Type type, MediaSinkInterface *sink);
|
||||||
ssize_t input(const uint8_t *data, size_t bytes);
|
ssize_t input(const uint8_t *data, size_t bytes);
|
||||||
|
void clearInputCache();
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -146,6 +146,12 @@ ssize_t TSDecoder::input(const uint8_t *data, size_t bytes) {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSDecoder::clearInputCache() {
|
||||||
|
// 只清理未完成的 TS 输入缓存,不重置 libmpegts 或 flush 残留帧。
|
||||||
|
// Clear only incomplete TS input; do not reset libmpegts or flush pending frames.
|
||||||
|
_ts_segment.reset();
|
||||||
|
}
|
||||||
|
|
||||||
#endif//defined(ENABLE_HLS)
|
#endif//defined(ENABLE_HLS)
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
TSDecoder();
|
TSDecoder();
|
||||||
~TSDecoder();
|
~TSDecoder();
|
||||||
ssize_t input(const uint8_t* data, size_t bytes) override ;
|
ssize_t input(const uint8_t* data, size_t bytes) override ;
|
||||||
|
void clearInputCache() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSSegment _ts_segment;
|
TSSegment _ts_segment;
|
||||||
|
|||||||
Reference in New Issue
Block a user