OWT (Open WebRTC Toolkit) 混屏模塊代碼邏輯

owt

Open WebRTC Toolkit Media Server
The media server for OWT provides an efficient video conference and streaming service that is based on WebRTC

基本概念

owt中的混屏是在類VideoMixer中實現(xiàn)的事示,owt-server/source/agent/video/videoMixer/VideoMixer.h

VideoMixer實現(xiàn)了根據(jù)指定的布局:layoutSolution 生成混屏視頻的能力亚隙。包括幾個基本概念:

input

input表示輸入圖像的流寸五,每個input有一個整數(shù)的inputIndex

通過addInput添加input招刹,其中FrameSource,會提供待解碼的數(shù)據(jù)鱼炒,來源于webrtc的videoReceiveStream渠鸽,由VideoMixer內(nèi)部解碼

bool VideoMixer::addInput(const int inputIndex, const std::string& codec, owt_base::FrameSource* source, const std::string& avatar)

output

output表示需要混屏的輸出流,每一個output有一個字符串outStreamID,在內(nèi)部被映射為一個唯一的int outputIndex

bool VideoMixer::addOutput(
    const std::string& outStreamID
    , const std::string& codec
    , const owt_base::VideoCodecProfile profile
    , const std::string& resolution
    , const unsigned int framerateFPS
    , const unsigned int bitrateKbps
    , const unsigned int keyFrameIntervalSeconds
    , owt_base::FrameDestination* dest)

FrameDestination 送到VideoSendStream墨缘,進(jìn)行編碼和打包為rtp包

layoutSolution

layoutSolution是一個混屏圖像的布局描述信息星虹,包括每個區(qū)域的坐標(biāo),大小等信息镊讼,最重要的是每一個區(qū)域包括一個inputIndex宽涌,混屏線程根據(jù)inputIndex去查找這個流的最后一幀圖像

所有布局的變化都體現(xiàn)在layoutSolution中。
一個VideoMixer只支持一個布局蝶棋,所有output都是同一個布局卸亮。

void VideoMixer::updateLayoutSolution(LayoutSolution& solution);

VideoMixer內(nèi)部邏輯

一、VideoMixer

VideoMixer內(nèi)部包含一個VideoFrameMixer m_frameMixer玩裙,VideoMixer只是對外部提供簡單的api兼贸,并沒有什么實際的工作。工作全部交給VideoFrameMixer完成吃溅。

VideoMixer的意義:

1溶诞、對外提供簡單api

2、將外部string類型的outputStreamId轉(zhuǎn)換為VideoFrameMixer需要的整數(shù)outputIndex

二决侈、VideoFrameMixer

VideoFrameMixer完成了input數(shù)據(jù)的解碼工作螺垢,解碼器是在VideoFrameMixerImpl::addInput這里創(chuàng)建的,并且將流程串聯(lián)起來赖歌,形成了inputsource->decoder->compositorIn->m_compositor的流程

bool VideoFrameMixerImpl::addInput(int input, owt_base::FrameFormat format, owt_base::FrameSource* source, const std::string& avatar) {
    boost::shared_ptr<CompositeIn> compositorIn(new CompositeIn(input, avatar, m_compositor));
    source->addVideoDestination(decoder.get());
    decoder->addVideoDestination(compositorIn.get());
}

VideoFrameMixer的意義:

1枉圃、完成數(shù)據(jù)解碼

2、串聯(lián)工作流程

3庐冯、給內(nèi)部的SoftVideoCompositor::m_compositor提供輸入圖像

三孽亲、SoftVideoCompositor

SoftVideoCompositor完成了不同幀率,相同布局的outout的混屏工作展父。

對于不同幀率墨林,巧妙的通過內(nèi)部的2個SoftFrameGenerator,來生成不同幀率的混屏數(shù)據(jù)犯祠。

SoftVideoCompositor::SoftVideoCompositor(uint32_t maxInput, VideoSize rootSize, YUVColor bgColor, bool crop)
    : m_maxInput(maxInput)
{
    m_inputs.resize(m_maxInput);
    for (auto& input : m_inputs) {
        input.reset(new SoftInput());
    }
    m_avatarManager.reset(new AvatarManager(maxInput));
    m_generators.resize(2);
    m_generators[0].reset(new SoftFrameGenerator(this, rootSize, bgColor, crop, 60, 15));
    m_generators[1].reset(new SoftFrameGenerator(this, rootSize, bgColor, crop, 48, 6));
}

通過構(gòu)造函數(shù)可以看到旭等,SoftVideoCompositor保存了input,input的數(shù)據(jù)衡载,通過上層工作流中的compositorIn調(diào)用pushInput輸入進(jìn)來搔耕,并進(jìn)行緩存:

void SoftVideoCompositor::pushInput(int input, const Frame& frame)
{
    assert(frame.format == owt_base::FRAME_FORMAT_I420);
    webrtc::VideoFrame* i420Frame = reinterpret_cast<webrtc::VideoFrame*>(frame.payload);
    m_inputs[input]->pushInput(i420Frame);
}

2個SoftFrameGenerator,分別處理了一批相關(guān)的幀率的混屏工作,比如:

FPS為15 30 60在m_generators[0]中混屏

FPS為6 12 24 48在m_generators[1]中混屏

SoftFrameGenerator的意義:

1弃榨、為所有output緩存公用的輸入圖像

2菩收、將不同幀率,交給擅長某個幀率處理的SoftFrameGenerator中處理鲸睛,節(jié)省混屏次數(shù)娜饵,從而節(jié)省性能

四、SoftFrameGenerator

SoftFrameGenerator是真正做混屏工作的類官辈,它處理2倍關(guān)系的一批幀率的output的混屏工作箱舞。

混屏工作,通過timer線程進(jìn)行觸發(fā)拳亿,最終執(zhí)行到SoftFrameGenerator::onTimeout()函數(shù)中晴股,做混屏的具體計算

此函數(shù)內(nèi)部,通過m_counter變量肺魁,巧妙的實現(xiàn)了不同幀率只需混屏一次的性能優(yōu)化电湘。

onTimeout會按照最大幀率來觸發(fā),通過下面的核心代碼鹅经,判斷了是否需要混屏寂呛,混屏后是否需要回調(diào),觸發(fā)哪個幀率的output的回調(diào)

bool hasValidOutput = false;
    {
        boost::unique_lock<boost::shared_mutex> lock(m_outputMutex);
        for (uint32_t i = 0; i < m_outputs.size(); i++) {
            if (m_counter % (i + 1)) 
                continue;
            if (m_outputs[i].size() > 0) {
                hasValidOutput = true;
                break;
            }
        }
    }

這個邏輯很巧妙瘾晃,但理解起來有點困難昧谊,可以通過下圖進(jìn)行理解:

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市酗捌,隨后出現(xiàn)的幾起案子呢诬,更是在濱河造成了極大的恐慌,老刑警劉巖胖缤,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尚镰,死亡現(xiàn)場離奇詭異,居然都是意外死亡哪廓,警方通過查閱死者的電腦和手機狗唉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涡真,“玉大人分俯,你說我怎么就攤上這事《吡希” “怎么了缸剪?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長东亦。 經(jīng)常有香客問我杏节,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任奋渔,我火速辦了婚禮镊逝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫉鲸。我一直安慰自己撑蒜,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布玄渗。 她就那樣靜靜地躺著座菠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捻爷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天份企,我揣著相機與錄音也榄,去河邊找鬼。 笑死司志,一個胖子當(dāng)著我的面吹牛甜紫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骂远,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼囚霸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了激才?” 一聲冷哼從身側(cè)響起拓型,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘸恼,沒想到半個月后劣挫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡东帅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年压固,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片靠闭。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡帐我,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出愧膀,到底是詐尸還是另有隱情拦键,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布檩淋,位于F島的核電站矿咕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碳柱,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一捡絮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莲镣,春花似錦福稳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至半火,卻和暖如春越妈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钮糖。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工梅掠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人店归。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓阎抒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親消痛。 傳聞我的和親對象是個殘疾皇子且叁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354