衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenHarmony 3.2 Beta多媒體系列:音視頻播放框架

電子發(fā)燒友開(kāi)源社區(qū) ? 來(lái)源:未知 ? 2022-11-23 09:40 ? 次閱讀

巴延興

深圳開(kāi)鴻數(shù)字產(chǎn)業(yè)發(fā)展有限公司

資深OS框架開(kāi)發(fā)工程師

以下內(nèi)容來(lái)自嘉賓分享,不代表開(kāi)放原子開(kāi)源基金會(huì)觀點(diǎn)

一、簡(jiǎn)介

媒體子系統(tǒng)為開(kāi)發(fā)者提供一套接口,方便開(kāi)發(fā)者使用系統(tǒng)的媒體資源,主要包含音視頻開(kāi)發(fā)、相機(jī)開(kāi)發(fā)、流媒體開(kāi)發(fā)等模塊。每個(gè)模塊都提供給上層應(yīng)用對(duì)應(yīng)的接口,本文會(huì)對(duì)音視頻開(kāi)發(fā)中的音視頻播放框架做一個(gè)詳細(xì)的介紹。

二、目錄

foundation/multimedia/media_standard
├── frameworks                        #框架代碼
│ ├── js
│ │ ├── player
│ ├── native
│ │ ├── player                    #native實(shí)現(xiàn)
│ └── videodisplaymanager         #顯示管理
│     ├── include
│     └── src
├── interfaces
│ ├── inner_api                     #內(nèi)部接口
│ │ └── native
│ └── kits                          #外部JS接口
├── sa_profile                        #服務(wù)配置文件
└── services
  ├── engine                        #engine代碼
  │ └── gstreamer
  ├── etc                           #服務(wù)配置文件
  ├── include                       #頭文件
  └── services
    ├── sa_media                  #media服務(wù)
    │ ├── client                #media客戶端
    │ ├── ipc                   #media ipc調(diào)用
    │ └── server                #media服務(wù)端
    ├── factory                   #engine工廠
    └── player                    #player服務(wù)
     ├── client                 #player客戶端
      ├── ipc                    #player ipc調(diào)用
└──server#player服務(wù)端

三、播放的總體流程

ab3cba20-6acf-11ed-8abf-dac502259ad0.png ?

四、Native接口使用

OpenHarmony系統(tǒng)中,音視頻播放通過(guò)N-API接口提供給上層JS調(diào)用,N-API相當(dāng)于是JS和Native之間的橋梁,在OpenHarmony源碼中,提供了C++直接調(diào)用的音視頻播放例子,在foundation/multimedia/player_framework/test/nativedemo/player目錄中。
void PlayerDemo::RunCase(const string &path)
{
    player_ = OHOS::CreatePlayer();
    if (player_ == nullptr) {
        cout << "player_ is null" << endl;
        return;
    }
    RegisterTable();
    std::shared_ptr cb = std::make_shared();
    cb->SetBufferingOut(SelectBufferingOut());


    int32_t ret = player_->SetPlayerCallback(cb);
    if (ret != 0) {
        cout << "SetPlayerCallback fail" << endl;
    }
    if (SelectSource(path) != 0) {
        cout << "SetSource fail" << endl;
        return;
    }
    sptr producerSurface = nullptr;
    producerSurface = GetVideoSurface();
    if (producerSurface != nullptr) {
        ret = player_->SetVideoSurface(producerSurface);
        if (ret != 0) {
            cout << "SetVideoSurface fail" << endl;
        }
    }
    SetVideoScaleType();
    if (SelectRendererMode() != 0) {
        cout << "set renderer info fail" << endl;
    }
    ret = player_->PrepareAsync();
    if (ret !=  0) {
        cout << "PrepareAsync fail" << endl;
        return;
    }
    cout << "Enter your step:" << endl;
    DoNext();
}
首先根據(jù)RunCase可以大致了解一下播放音視頻的主要流程,創(chuàng)建播放器,設(shè)置播放源,設(shè)置回調(diào)方法(包含播放過(guò)程中的多種狀態(tài)的回調(diào)),設(shè)置播放顯示的Surface,這些準(zhǔn)備工作做好之后,需要調(diào)用播放器的PrepareASync方法,這個(gè)方法完成后,播放狀態(tài)會(huì)變成Prepared狀態(tài),這時(shí)就可以調(diào)用播放器的play接口,進(jìn)行音視頻的播放了。 RegisterTable()方法中,將字符串和對(duì)應(yīng)的方法映射到Map中,這樣后續(xù)的DoNext會(huì)根據(jù)輸入的命令,來(lái)決定播放器具體的操作。
void PlayerDemo::DoNext()
{
    std::string cmd;
    while (std::cin, cmd)) {
        auto iter = playerTable_.find(cmd);
        if (iter != playerTable_.end()) {
            auto func = iter->second;
            if (func() != 0) {
                cout << "Operation error" << endl;
            }
            if (cmd.find("stop") != std::npos && dataSrc_ != nullptr) {
                dataSrc_->Reset();
            }
            continue;
        } else if (cmd.find("quit") != std::npos || cmd == "q") {
            break;
        } else {
            DoCmd(cmd);
            continue;
        }
    }
}


void PlayerDemo::RegisterTable()
{
    (void)playerTable_.emplace("prepare", std::bind(&Player::Prepare, player_));
    (void)playerTable_.emplace("prepareasync", std::bind(&Player::PrepareAsync, player_));
    (void)playerTable_.emplace("", std::bind(&Player::Play, player_)); // ENTER -> play
    (void)playerTable_.emplace("play", std::bind(&Player::Play, player_));
    (void)playerTable_.emplace("pause", std::bind(&Player::Pause, player_));
    (void)playerTable_.emplace("stop", std::bind(&Player::Stop, player_));
    (void)playerTable_.emplace("reset", std::bind(&Player::Reset, player_));
    (void)playerTable_.emplace("release", std::bind(&Player::Release, player_));
    (void)playerTable_.emplace("isplaying", std::bind(&PlayerDemo::GetPlaying, this));
    (void)playerTable_.emplace("isloop", std::bind(&PlayerDemo::GetLooping, this));
    (void)playerTable_.emplace("speed", std::bind(&PlayerDemo::GetPlaybackSpeed, this));
}
以上的DoNext方法中核心的代碼是func()的調(diào)用,這個(gè)func就是之前注冊(cè)進(jìn)Map中字符串對(duì)應(yīng)的方法,在RegisterTable方法中將空字符串""和"play"對(duì)綁定為Player::Play方法,默認(rèn)不輸入命令參數(shù)時(shí),是播放操作。

五、調(diào)用流程

ab47b74a-6acf-11ed-8abf-dac502259ad0.jpgab6a3888-6acf-11ed-8abf-dac502259ad0.jpg ? ?

左右滑動(dòng)查看更多

本段落主要針對(duì)媒體播放的框架層代碼進(jìn)行分析,所以在流程中涉及到了IPC調(diào)用相關(guān)的客戶端和服務(wù)端,代碼暫且分析到調(diào)用gstreamer引擎。 首先Sample通過(guò)PlayerFactory創(chuàng)建了一個(gè)播放器實(shí)例(PlayerImpl對(duì)象),創(chuàng)建過(guò)程中調(diào)用Init函數(shù)。
int32_t PlayerImpl::Init()
{
    playerService_ = MediaServiceFactory::GetInstance().CreatePlayerService();
    CHECK_AND_RETURN_RET_LOG(playerService_ != nullptr, MSERR_UNKNOWN, "failed to create player service");
    return MSERR_OK;
}
MediaServiceFactory::GetInstance()返回的是MediaClient對(duì)象,所以CreateplayerService函數(shù)實(shí)際上是調(diào)用了MediaClient對(duì)應(yīng)的方法。
std::shared_ptr MediaClient::CreatePlayerService()
{
    std::lock_guard lock(mutex_);
    if (!IsAlived()) {
        MEDIA_LOGE("media service does not exist.");
        return nullptr;
    }


    sptr object = mediaProxy_->GetSubSystemAbility(
        IStandardMediaService::MEDIA_PLAYER, listenerStub_->AsObject());
    CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "player proxy object is nullptr.");


    sptr playerProxy = iface_cast(object);
    CHECK_AND_RETURN_RET_LOG(playerProxy != nullptr, nullptr, "player proxy is nullptr.");


    std::shared_ptr player = PlayerClient::Create(playerProxy);
    CHECK_AND_RETURN_RET_LOG(player != nullptr, nullptr, "failed to create player client.");


    playerClientList_.push_back(player);
    return player;
}
這個(gè)方法中主要通過(guò)PlayerClient::Create(playerProxy)方法創(chuàng)建了PlayerClient實(shí)例,并且將該實(shí)例一層層向上傳,最終傳給了PlayerImpl的playerService_變量,后續(xù)對(duì)于播放器的操作,PlayerImpl都是通過(guò)調(diào)用PlayerClient實(shí)例實(shí)現(xiàn)的。
int32_t PlayerImpl::Play()
{
    CHECK_AND_RETURN_RET_LOG(playerService_ != nullptr, MSERR_INVALID_OPERATION, "player service does not exist..");
    MEDIA_LOGW("KPI-TRACE: PlayerImpl Play in");
    return playerService_->Play();
}


int32_t PlayerImpl::Prepare()
{
    CHECK_AND_RETURN_RET_LOG(playerService_ != nullptr, MSERR_INVALID_OPERATION, "player service does not exist..");
    MEDIA_LOGW("KPI-TRACE: PlayerImpl Prepare in");
    return playerService_->Prepare();
}


int32_t PlayerImpl::PrepareAsync()
{
    CHECK_AND_RETURN_RET_LOG(playerService_ != nullptr, MSERR_INVALID_OPERATION, "player service does not exist..");
    MEDIA_LOGW("KPI-TRACE: PlayerImpl PrepareAsync in");
    return playerService_->PrepareAsync();
}
對(duì)于PlayerImpl來(lái)說(shuō),playerService_指向的PlayerClient就是具體的實(shí)現(xiàn),PlayerClient的實(shí)現(xiàn)是通過(guò)IPC的遠(yuǎn)程調(diào)用來(lái)實(shí)現(xiàn)的,具體地是通過(guò)IPC中的proxy端向遠(yuǎn)端服務(wù)發(fā)起遠(yuǎn)程調(diào)用請(qǐng)求。 我們以播放Play為例:
int32_t PlayerClient::Play()
{
    std::lock_guard lock(mutex_);
    CHECK_AND_RETURN_RET_LOG(playerProxy_ != nullptr, MSERR_NO_MEMORY, "player service does not exist..");
    return playerProxy_->Play();
}
int32_t PlayerServiceProxy::Play()
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option;


    if (!data.WriteInterfaceToken(PlayerServiceProxy::GetDescriptor())) {
        MEDIA_LOGE("Failed to write descriptor");
        return MSERR_UNKNOWN;
    }


    int error = Remote()->SendRequest(PLAY, data, reply, option);
    if (error != MSERR_OK) {
        MEDIA_LOGE("Play failed, error: %{public}d", error);
        return error;
    }
    return reply.ReadInt32();
}
proxy端發(fā)送調(diào)用請(qǐng)求后,對(duì)應(yīng)的Stub端會(huì)在PlayerServiceStub::OnRemoteRequest接收到請(qǐng)求,根據(jù)請(qǐng)求的參數(shù)進(jìn)行對(duì)應(yīng)的函數(shù)調(diào)用。播放操作對(duì)應(yīng)的調(diào)用Stub的Play方法。
int32_t PlayerServiceStub::Play()
{
    MediaTrace Trace("binder::Play");
    CHECK_AND_RETURN_RET_LOG(playerServer_ != nullptr, MSERR_NO_MEMORY, "player server is nullptr");
    return playerServer_->Play();
}
這里最終是通過(guò)playerServer_調(diào)用Play函數(shù)。playerServer_在Stub初始化的時(shí)候通過(guò)PlayerServer::Create()方式來(lái)獲取得到。也就是PlayerServer。
std::shared_ptr PlayerServer::Create()
{
    std::shared_ptr server = std::make_shared();
    CHECK_AND_RETURN_RET_LOG(server != nullptr, nullptr, "failed to new PlayerServer");


    (void)server->Init();
    return server;
}
最終我們的Play調(diào)用到了PlayerServer的Play()。在媒體播放的整個(gè)過(guò)程中會(huì)涉及到很多的狀態(tài),所以在Play中進(jìn)行一些狀態(tài)的判讀后調(diào)用OnPlay方法。這個(gè)方法中發(fā)起了一個(gè)播放的任務(wù)。
int32_t PlayerServer::Play()
{
    std::lock_guard lock(mutex_);


    if (lastOpStatus_ == PLAYER_PREPARED || lastOpStatus_ == PLAYER_PLAYBACK_COMPLETE ||
        lastOpStatus_ == PLAYER_PAUSED) {
        return OnPlay();
    } else {
        MEDIA_LOGE("Can not Play, currentState is %{public}s", GetStatusDescription(lastOpStatus_).c_str());
        return MSERR_INVALID_OPERATION;
    }
}


int32_t PlayerServer::OnPlay()
{
    auto playingTask = std::make_shared>([this]() {
        MediaTrace::TraceBegin("PlayerServer::Play", FAKE_POINTER(this));
        auto currState = std::static_pointer_cast(GetCurrState());
        (void)currState->Play();
    });


    int ret = taskMgr_.LaunchTask(playingTask, PlayerServerTaskType::STATE_CHANGE);
    CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Play failed");


    lastOpStatus_ = PLAYER_STARTED;
    return MSERR_OK;
}
在播放任務(wù)中調(diào)用了PlayerServer::Play()
int32_t PlayerServer::Play()
{
    return server_.HandlePlay();
}
在Play里面直接調(diào)用PlayerServer的HandlePlay方法,HandlePlay方法通過(guò)playerEngine_調(diào)用到了gstreamer引擎,gstreamer是最終播放的實(shí)現(xiàn)。
int32_t PlayerServer::HandlePlay()
{
    int32_t ret = playerEngine_->Play();
    CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_OPERATION, "Engine Play Failed!");


    return MSERR_OK;
}

六、總結(jié)

本文主要對(duì)OpenHarmony 3.2 Beta多媒體子系統(tǒng)的媒體播放進(jìn)行介紹,首先梳理了整體的播放流程,然后對(duì)播放的主要步驟進(jìn)行了詳細(xì)地分析。 媒體播放主要分為以下幾個(gè)層次:

(1)提供給應(yīng)用調(diào)用的Native接口,這個(gè)實(shí)際上通過(guò)OHOS::CreatePlayer()調(diào)用返回PlayerImpl實(shí)例。

(2)PlayerClient,這部分通過(guò)IPC的proxy調(diào)用,向遠(yuǎn)程服務(wù)發(fā)起調(diào)用請(qǐng)求。

(3)PlayerServer,這部分是播放服務(wù)的實(shí)現(xiàn)端,提供給Client端調(diào)用。

(4)Gstreamer,這部分是提供給PlayerServer調(diào)用,真正實(shí)現(xiàn)媒體播放的功能。

更多熱點(diǎn)文章閱讀

  • 玩嗨OpenHarmony:基于OpenHarmony的智能助老服務(wù)機(jī)器人
  • 玩嗨OpenHarmony:基于OpenHarmony的智慧農(nóng)業(yè)環(huán)境監(jiān)控系統(tǒng)
  • 基于OpenHarmony的智慧牧場(chǎng)方案:生物姿態(tài)檢測(cè)
  • 基于OpenHarmony的智慧牧場(chǎng)方案:生物心率檢測(cè)篇
  • 使用ADS1115擴(kuò)展ROC-RK3568-PC開(kāi)發(fā)板ADC功能

提示:本文由電子發(fā)燒友社區(qū)發(fā)布,轉(zhuǎn)載請(qǐng)注明以上來(lái)源。如需社區(qū)合作及入群交流,請(qǐng)?zhí)砑游⑿臙EFans0806,或者發(fā)郵箱liuyong@huaqiu.com。


原文標(biāo)題:OpenHarmony 3.2 Beta多媒體系列:音視頻播放框架

文章出處:【微信公眾號(hào):電子發(fā)燒友開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:OpenHarmony 3.2 Beta多媒體系列:音視頻播放框架

文章出處:【微信號(hào):HarmonyOS_Community,微信公眾號(hào):電子發(fā)燒友開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何在音頻播放時(shí)插播音頻

    ZDP14x0系列芯片是內(nèi)置開(kāi)源GUI引擎的圖像顯示專用驅(qū)動(dòng)芯片,內(nèi)部集成16MB/64MB顯示內(nèi)存、2D圖形加速器、音視頻解碼器等豐富多媒體功能。不僅支持音視頻
    的頭像 發(fā)表于 11-25 15:40 ?735次閱讀
    如何在音頻<b class='flag-5'>播放</b>時(shí)插播音頻

    dm368錄制音視頻后用vlc播放不同步是怎么回事?

    目前我們用其他的開(kāi)發(fā)板 能夠錄制音視頻,但是用vlc播放的時(shí)候發(fā)現(xiàn)每次都是視頻播放完成了音頻還要播放一會(huì),隨著錄制時(shí)間加上,延后的這個(gè)時(shí)間
    發(fā)表于 10-15 06:56

    盤(pán)點(diǎn)那些常見(jiàn)音視頻接口

    我們熟知的一些常見(jiàn)音視頻接口,發(fā)展至今在日常使用中已經(jīng)漸漸少了。但是在工業(yè)領(lǐng)域的音視頻連接,依然能看到其身影。這些看似消失的接口,它們現(xiàn)在發(fā)展成什么樣子了?本期我們將做一個(gè)大盤(pán)點(diǎn)。
    的頭像 發(fā)表于 09-09 14:34 ?694次閱讀

    常見(jiàn)音視頻接口的靜電浪涌防護(hù)和濾波方案

    音視頻接口在現(xiàn)代多媒體設(shè)備中扮演著至關(guān)重要的角色,它們確保了音視頻信號(hào)在不同設(shè)備間的順暢傳輸,各種類型的音視頻接口滿足了多樣化的應(yīng)用場(chǎng)景需求。 在
    的頭像 發(fā)表于 06-25 11:28 ?763次閱讀

    音視頻產(chǎn)品EMC整改案例解析

    音視頻產(chǎn)品EMCRE整改案例解析
    的頭像 發(fā)表于 05-20 16:49 ?501次閱讀
    <b class='flag-5'>音視頻</b>產(chǎn)品EMC整改案例解析

    分享一款高清HDMI音視頻采集編碼卡,支持雙碼流

    “靈卡CAS”系列HDMI音視頻采集卡。獨(dú)具匠心的設(shè)計(jì)與功能配置,適用于各種規(guī)模的商務(wù)會(huì)議、多媒體教育以及數(shù)字化展示等各類場(chǎng)景。
    的頭像 發(fā)表于 05-07 11:43 ?461次閱讀
    分享一款高清HDMI<b class='flag-5'>音視頻</b>采集編碼卡,支持雙碼流

    【RTC程序設(shè)計(jì):實(shí)時(shí)音視頻權(quán)威指南】音視頻的編解碼壓縮技術(shù)

    音視頻所載有的信息在通過(guò)傳輸?shù)臅r(shí)候就需要壓縮編碼。 其中,文本壓縮是指通過(guò)使用各種算法和技術(shù),將文本數(shù)據(jù)表示為更緊湊的形式,以減少存儲(chǔ)空間。 霍夫曼編碼是一種無(wú)損壓縮算法,它可以根據(jù)字符出現(xiàn)
    發(fā)表于 04-28 21:04

    鴻蒙媒體開(kāi)發(fā)【簡(jiǎn)述】

    媒體系統(tǒng)架構(gòu) 媒體系統(tǒng)提供用戶視覺(jué)、聽(tīng)覺(jué)信息的處理能力,如音視頻信息的采集、壓縮存儲(chǔ)、解壓播放等。在操作系統(tǒng)實(shí)現(xiàn)中,通常基于不同的媒體信息處
    發(fā)表于 02-28 17:53

    OpenHarmony4.0源碼解析之媒體框架

    媒體框架簡(jiǎn)介 媒體框架 multimedia_player_framework 主要提供音視頻的錄制與
    的頭像 發(fā)表于 02-26 22:05 ?1099次閱讀
    <b class='flag-5'>OpenHarmony</b>4.0源碼解析之<b class='flag-5'>媒體</b><b class='flag-5'>框架</b>

    音視頻解碼生成:打造你的專屬高清影院體驗(yàn)

    在數(shù)字化時(shí)代,人們對(duì)觀影體驗(yàn)的要求越來(lái)越高。音視頻解碼生成技術(shù),作為現(xiàn)代多媒體播放的核心,正是為了滿足這種需求而不斷發(fā)展和完善的。通過(guò)這項(xiàng)技術(shù),我們可以輕松打造屬于自己的高清影院體驗(yàn)。 一、高清畫(huà)質(zhì)
    的頭像 發(fā)表于 02-25 14:47 ?444次閱讀

    音視頻解碼生成:打造極致觀影體驗(yàn)的關(guān)鍵技術(shù)

    在現(xiàn)代多媒體時(shí)代,音視頻解碼生成技術(shù)已成為提供極致觀影體驗(yàn)的核心要素。它不僅能夠確保音視頻數(shù)據(jù)的高效傳輸,還能保證播放的流暢性和畫(huà)質(zhì)清晰度,為用戶帶來(lái)身臨其境的觀影享受。 1. 解碼生
    的頭像 發(fā)表于 02-25 14:43 ?513次閱讀

    音視頻解碼器優(yōu)化技巧:提升播放體驗(yàn)的關(guān)鍵步驟

    隨著數(shù)字多媒體內(nèi)容的爆炸式增長(zhǎng),音視頻解碼器在現(xiàn)代技術(shù)生活中扮演著至關(guān)重要的角色。從流暢的在線視頻播放到高質(zhì)量的本地文件解碼,解碼器的性能直接影響了我們的觀看體驗(yàn)。那么,如何優(yōu)化
    的頭像 發(fā)表于 02-21 14:45 ?940次閱讀

    音視頻解碼器硬件加速:實(shí)現(xiàn)更流暢的播放效果

    隨著多媒體內(nèi)容的日益豐富和高清化,傳統(tǒng)的軟件解碼已經(jīng)難以滿足人們對(duì)流暢播放體驗(yàn)的需求。因此,音視頻解碼器硬件加速技術(shù)的出現(xiàn),為提升播放效果帶來(lái)了革命性的改變。 硬件加速的原理 硬件加速
    的頭像 發(fā)表于 02-21 14:40 ?1063次閱讀
    <b class='flag-5'>音視頻</b>解碼器硬件加速:實(shí)現(xiàn)更流暢的<b class='flag-5'>播放</b>效果

    音視頻解碼生成在多媒體制作中的應(yīng)用

    音視頻解碼生成是多媒體制作中不可或缺的一部分,它扮演著將編碼的音視頻數(shù)據(jù)轉(zhuǎn)化為可播放、可編輯的內(nèi)容的關(guān)鍵角色。在多媒體制作的全過(guò)程中,
    的頭像 發(fā)表于 02-21 14:39 ?423次閱讀

    音視頻解碼生成與流媒體傳輸?shù)慕Y(jié)合

    音視頻解碼生成與流媒體傳輸是現(xiàn)代數(shù)字媒體技術(shù)中兩個(gè)不可或缺的部分,它們的結(jié)合為用戶提供了高質(zhì)量、實(shí)時(shí)性的多媒體體驗(yàn)。 1. 解碼生成與流媒體
    的頭像 發(fā)表于 02-21 14:36 ?448次閱讀
    百家乐官网大眼仔用法| 帝王百家乐的玩法技巧和规则| 海王星线上娱乐| 百家乐官网定位胆技巧| 香港六合彩特码| 百家乐视频游戏大厅| 百家乐官网能赚大钱吗| 大发888网页登陆| 百家乐最新投注法| 金城百家乐官网玩法平台| 大发888 赌博网站| 至尊百家乐20111110| 百家乐官网有真假宝单吗| 百家乐过滤工具| 百家乐有什么打法| 百家乐官网过两关| 六合彩挂牌| 百家乐博娱乐赌百家乐的玩法技巧和规则 | 百家乐官网注册送免费金| 大发888下载专区| 保时捷百家乐娱乐城| 女神百家乐官网娱乐城| 万博88真人娱乐城| 百家乐五湖四海娱乐| 百家乐官网图形的秘密破解| 百家乐投注| 在线百家乐作弊| 玩百家乐官网去哪个娱乐城最安全| 轮盘必胜法| 大发888大赢家| 百家乐黄金城游戏大厅| 百家乐官网的分析| 百家乐官网的必赢术| 大发888娱乐亚洲| 百家乐哪条路准| 阴宅24水口| 澳门百家乐官网玩法与游戏规则| 德州扑克 | 真人游戏平台| 信誉百家乐平台| 发中发百家乐官网的玩法技巧和规则|