MediaSink.cpp 5.33 KB
Newer Older
1 2 3
/*
 * MIT License
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "MediaSink.h"

28
//最多等待未初始化的Track 10秒,超时之后会忽略未初始化的Track
29 30 31 32 33
#define MAX_WAIT_MS_READY 10000

//如果添加Track,最多等待3秒
#define MAX_WAIT_MS_ADD_TRACK 3000

34 35 36 37

namespace mediakit{

void MediaSink::addTrack(const Track::Ptr &track_in) {
38
    lock_guard<recursive_mutex> lck(_mtx);
39
    //克隆Track,只拷贝其数据,不拷贝其数据转发关系
40 41 42
    auto track = track_in->clone();
    auto codec_id = track->getCodecId();
    _track_map[codec_id] = track;
43 44
    _allTrackReady = false;
    _trackReadyCallback[codec_id] = [this, track]() {
45 46
        onTrackReady(track);
    };
47
    _ticker.resetTime();
xiongziliang committed
48

49 50
    track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
        if (_allTrackReady) {
xiongziliang committed
51
            onTrackFrame(frame);
xiongziliang committed
52 53
        }
    }));
54 55
}

56
void MediaSink::resetTracks() {
xiongziliang committed
57
    lock_guard<recursive_mutex> lck(_mtx);
58 59 60 61
    _allTrackReady = false;
    _track_map.clear();
    _trackReadyCallback.clear();
    _ticker.resetTime();
62
    _max_track_size = 2;
63 64
}

65
void MediaSink::inputFrame(const Frame::Ptr &frame) {
66
    lock_guard<recursive_mutex> lck(_mtx);
67
    auto it = _track_map.find(frame->getCodecId());
68 69 70 71
    if (it == _track_map.end()) {
        return;
    }
    it->second->inputFrame(frame);
72 73 74 75 76 77 78 79 80 81 82
    checkTrackIfReady(it->second);
}

void MediaSink::checkTrackIfReady_l(const Track::Ptr &track){
    //Track由未就绪状态转换成就绪状态,我们就触发onTrackReady回调
    auto it_callback = _trackReadyCallback.find(track->getCodecId());
    if (it_callback != _trackReadyCallback.end() && track->ready()) {
        it_callback->second();
        _trackReadyCallback.erase(it_callback);
    }
}
83

84 85 86 87 88 89 90 91
void MediaSink::checkTrackIfReady(const Track::Ptr &track){
    if (!_allTrackReady && !_trackReadyCallback.empty()) {
        if (track) {
            checkTrackIfReady_l(track);
        } else {
            for (auto &pr : _track_map) {
                checkTrackIfReady_l(pr.second);
            }
92 93 94
        }
    }

95 96 97
    if(!_allTrackReady){
        if(_ticker.elapsedTime() > MAX_WAIT_MS_READY){
            //如果超过规定时间,那么不再等待并忽略未准备好的Track
98
            emitAllTrackReady();
99 100 101
            return;
        }

102
        if(!_trackReadyCallback.empty()){
103 104
            //在超时时间内,如果存在未准备好的Track,那么继续等待
            return;
105 106
        }

107
        if(_track_map.size() == _max_track_size){
108
            //如果已经添加了音视频Track,并且不存在未准备好的Track,那么说明所有Track都准备好了
109
            emitAllTrackReady();
110
            return;
111
        }
112 113 114

        if(_track_map.size() == 1 && _ticker.elapsedTime() > MAX_WAIT_MS_ADD_TRACK){
            //如果只有一个Track,那么在该Track添加后,我们最多还等待若干时间(可能后面还会添加Track)
115
            emitAllTrackReady();
116 117 118 119 120
            return;
        }
    }
}

121
void MediaSink::addTrackCompleted(){
122 123 124 125 126
    {
        lock_guard<recursive_mutex> lck(_mtx);
        _max_track_size = _track_map.size();
    }
    checkTrackIfReady(nullptr);
127 128 129
}

void MediaSink::emitAllTrackReady() {
130 131 132 133 134
    if (_allTrackReady) {
        return;
    }

    if (!_trackReadyCallback.empty()) {
135 136 137
        //这是超时强制忽略未准备好的Track
        _trackReadyCallback.clear();
        //移除未准备好的Track
138 139
        for (auto it = _track_map.begin(); it != _track_map.end();) {
            if (!it->second->ready()) {
140
                WarnL << "该track长时间未被初始化,已忽略:" << it->second->getCodecName();
141 142 143 144 145 146 147
                it = _track_map.erase(it);
                continue;
            }
            ++it;
        }
    }

148
    if (!_track_map.empty()) {
149
        //最少有一个有效的Track
150
        _allTrackReady = true;
151
        onAllTrackReady();
152 153 154
    }
}

xiongziliang committed
155 156
vector<Track::Ptr> MediaSink::getTracks(bool trackReady) const{
    vector<Track::Ptr> ret;
157
    lock_guard<recursive_mutex> lck(_mtx);
158
    for (auto &pr : _track_map){
xiongziliang committed
159 160
        if(trackReady && !pr.second->ready()){
            continue;
161
        }
xiongziliang committed
162
        ret.emplace_back(pr.second);
163
    }
xiongziliang committed
164
    return std::move(ret);
165 166
}

167 168

}//namespace mediakit