鴻蒙屏幕捕后通過(guò)AVCodec Kit使用Surface模式編碼成h264

前一篇文章已經(jīng)把捕獲屏幕的功能實(shí)現(xiàn)卿城,現(xiàn)在我們要把捕獲的視頻數(shù)據(jù)編碼成264為后面保存成文件,或者通過(guò)流媒體的形式分發(fā)做準(zhǔn)備

鴻蒙avcodec kit編碼的關(guān)系圖如下

編碼調(diào)用關(guān)系官方圖

下面實(shí)現(xiàn)整個(gè)編碼過(guò)程

1唆姐,在CMake腳本中鏈接動(dòng)態(tài)庫(kù)

target_link_libraries(entry PUBLIC libace_napi.z.so                                    libnative_avscreen_capture.so                                    libhilog_ndk.z.so                                    libnative_media_core.so                                    libnative_buffer.so                                    libnative_media_codecbase.so                                    libnative_media_venc.so                                    libnative_media_acodec.so)        

2,新建video_encoder類廓八,并實(shí)現(xiàn)相關(guān)函數(shù)

視頻編碼器類中包括創(chuàng)建編碼器奉芦,配置編碼器,啟動(dòng)編碼器剧蹂,停止二號(hào)釋放編碼器

int32_t Create(const std::string &videoCodecMime);int32_t Config(VideoSampleInfo &sampleInfo, AVCodecUserData *codecUserData);int32_t Start();int32_t Stop();int32_t Release();

1声功,根據(jù)mine type創(chuàng)建編碼器,這里我們用的mine type是OH_AVCODEC_MIMETYPE_VIDEO_AVC就是h264

int32_t VideoEncoder::Create(const std::string &videoCodecMime){       // 通過(guò) MIME TYPE 創(chuàng)建編碼器宠叼,系統(tǒng)會(huì)根據(jù)MIME創(chuàng)建最合適的編碼器先巴。//     OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);//     const char *codecName = OH_AVCapability_GetName(capability);//     codec = OH_VideoEncoder_CreateByName(codecName);    encoder_ = OH_VideoEncoder_CreateByMime(videoCodecMime.c_str());    CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Create failed");    return AVCODEC_SAMPLE_ERR_OK;}

2,配置編碼器车吹,主要包括色彩格式筹裕,視頻寬度,視頻高度窄驹,視頻幀率朝卒,關(guān)鍵幀間隔,和編碼回調(diào)等

int32_t VideoEncoder::Config(VideoSampleInfo &sampleInfo, AVCodecUserData *codecUserData){    CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");    CHECK_AND_RETURN_RET_LOG(codecUserData != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Invalid param: codecUserData");    // Configure video encoder    int32_t ret = Configure(sampleInfo);    CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Configure failed");    // GetSurface from video encoder    ret = GetSurface(sampleInfo);    CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Get surface failed");        // SetCallback for video encoder    ret = SetCallback(codecUserData);    CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR,                             "Set callback failed, ret: %{public}d", ret);    // Prepare video encoder    ret = OH_VideoEncoder_Prepare(encoder_);    CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Prepare failed, ret: %{public}d", ret);    return AVCODEC_SAMPLE_ERR_OK;}

這里寫(xiě)了兩個(gè)輔助函數(shù)乐埠,

創(chuàng)建surface模式對(duì)應(yīng)的窗口

int32_t VideoEncoder::GetSurface(VideoSampleInfo &sampleInfo){    int32_t ret = OH_VideoEncoder_GetSurface(encoder_, &sampleInfo.window);    CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK && sampleInfo.window, AVCODEC_SAMPLE_ERR_ERROR,        "Get surface failed, ret: %{public}d", ret);    (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_BUFFER_GEOMETRY, sampleInfo.videoWidth,                                                sampleInfo.videoHeight);    (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_USAGE, 16425); // 16425: Window usage    (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_FORMAT,        ToGraphicPixelFormat(sampleInfo.pixelFormat, sampleInfo.isHDRVivid));    return AVCODEC_SAMPLE_ERR_OK;}

配置編碼器的相關(guān)回調(diào):編碼錯(cuò)誤回調(diào)抗斤,編碼格式更新回調(diào)囚企,編碼輸入緩存回調(diào)(這是surface模式,未使用)瑞眼,編碼輸出緩存回調(diào)

int32_t VideoEncoder::SetCallback(AVCodecUserData *codecUserData){    int32_t ret = OH_VideoEncoder_RegisterCallback(encoder_,    {VideoSampleCallback::OnCodecError, VideoSampleCallback::OnCodecFormatChange,        VideoSampleCallback::OnNeedInputBuffer, VideoSampleCallback::OnNewOutputBuffer},        codecUserData);    CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Set callback failed, ret: %{public}d", ret);    return AVCODEC_SAMPLE_ERR_OK;}

3龙宏,啟動(dòng)編碼器

int32_t VideoEncoder::Start(){    CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");    int ret = OH_VideoEncoder_Start(encoder_);    CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Start failed, ret: %{public}d", ret);    return AVCODEC_SAMPLE_ERR_OK;}

然后改造screen_capture

引入視頻編碼類,額外啟動(dòng)一個(gè)線程用來(lái)接受編碼后的數(shù)據(jù)伤疙,并寫(xiě)入文件

在CreateAndInitWithSurfaceMode函數(shù)中實(shí)例化視頻編碼器

在StartWithSurfaceMode函數(shù)中加入

在StopAndReleaseWithSurfaceMode添加停止編碼相關(guān)邏輯

這里我們把視頻保存成h264文件了银酗,文件地址如下

運(yùn)行測(cè)后會(huì)在手機(jī)報(bào)名目錄下生成文件

用ffplay播放文件顯示如下信息

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市徒像,隨后出現(xiàn)的幾起案子黍特,更是在濱河造成了極大的恐慌,老刑警劉巖锯蛀,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灭衷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡旁涤,警方通過(guò)查閱死者的電腦和手機(jī)翔曲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)劈愚,“玉大人瞳遍,你說(shuō)我怎么就攤上這事【穑” “怎么了傅蹂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)算凿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)犁功,這世上最難降的妖魔是什么氓轰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮浸卦,結(jié)果婚禮上署鸡,老公的妹妹穿的比我還像新娘。我一直安慰自己限嫌,他們只是感情好靴庆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著怒医,像睡著了一般炉抒。 火紅的嫁衣襯著肌膚如雪和泌。 梳的紋絲不亂的頭發(fā)上俐芯,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼属提。 笑死,一個(gè)胖子當(dāng)著我的面吹牛混聊,可吹牛的內(nèi)容都是我干的震蒋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼野瘦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼描沟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鞭光,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吏廉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后衰猛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體迟蜜,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年啡省,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了娜睛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卦睹,死狀恐怖畦戒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情结序,我是刑警寧澤障斋,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站徐鹤,受9級(jí)特大地震影響垃环,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜返敬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一遂庄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劲赠,春花似錦涛目、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至塑煎,卻和暖如春沫换,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背轧叽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工苗沧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刊棕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓待逞,卻偏偏與公主長(zhǎng)得像甥角,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子识樱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容