首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【android开发】Android binder学习一:主要概念

【android开发】Android binder学习一:主要概念

作者头像
程序员互动联盟
发布于 2018-03-13 08:39:43
发布于 2018-03-13 08:39:43
1K00
代码可运行
举报
运行总次数:0
代码可运行

要看得懂android代码,首先要了解binder机制。binder机制也是android里面比较难以理解的一块,这里记录一下binder的重要概念以及实现,作为备忘。部分内容来源于网上,如有侵权,请及时告知。

1.binder通信机制概述

binder通信是一种client-server的通信结构, 1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用; 2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的; 3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象; 4.代理接口将该Parcel发送给内核中的binder driver. 5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回; 6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

2.为什么使用binder通信

linux中有管道,system V IPC,socket等进程间通信机制,那么为什么在android中使用了一个全新的binder通信机制呢?

一、可靠性。在移动设备上,通常采用基于Client-Server的通信方式来实现互联网与设备间的内部通信。目前linux支持IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。Android系统为开发者提供了丰富进程间通信的功能接口,媒体播放,传感器,无线传输。这些功能都由不同的server来管理。开发都只关心将自己应用程序的client与server的通信建立起来便可以使用这个服务。毫无疑问,如若在底层架设一套协议来实现Client-Server通信,增加了系统的复杂性。在资源有限的手机 上来实现这种复杂的环境,可靠性难以保证。

二、传输性能。socket主要用于跨网络的进程间通信和本机上进程间的通信,但传输效率低,开销大。消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的一块缓存区中,然后从内核缓存区拷贝到接收方缓存区,其过程至少有两次拷贝。虽然共享内存无需拷贝,但控制复杂。比较各种IPC方式的数据拷贝次数。共享内存:0次。Binder:1次。Socket/管道/消息队列:2次。

IPC

数据拷贝次数

共享内存

0

Binder

1

Socket/管道/消息队列

2

三、安全性。Android是一个开放式的平台,所以确保应用程序安全是很重要的。Android对每一个安装应用都分配了UID/PID,其中进程的UID是可用来鉴别进程身份。传统的只能由用户在数据包里填写UID/PID,这样不可靠,容易被恶意程序利用。而我们要求由内核来添加可靠的UID。

基于以上原因,Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是Binder。Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。

3.service manager

顾名思义,service manager就是android下面管理service的一个进程,它本身也是一个service,这里的service和init.rc里面的service有一些差别,init.rc中的service都是一个进程,而这里的service可能不是一个单独的进程。每一个service在使用之前都必须向SM注册,每一个client要使用service前都应该先向SM查询是否存在这个service,如果存在,则给client返回这个service的handle。下面是sm中main函数的关键代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    ......

    //svcmgr_handle的值为0
    svcmgr_handle = BINDER_SERVICE_MANAGER;
    binder_loop(bs, svcmgr_handler);

    return 0;
}

在SM中主要做了如下工作:

  • 打开binder设备,映射128k的内存到应用空间。
  • 指定 svcmgr_handle的值为0,当client与SM通信时,需要先创建一个handle为0的代理binder。
  • binder_become_context_manager通知binder driver使SM为context manager。
  • binder_loop是一个死循环,里面不停的读binder是否有数据,如果有数据,则解析,对于BR_TRANSACTION,会调用svcmgr_handler来处理。
  • SM维护了一个svclist来存储service的信息。一个新的service需要向SM注册add到这个列表,而client请求时会在svclist里面查找请求的service。一个service包括两个重要的信息,handle和name。add和get都会根据name来进行匹配。

下面一个图片可以简单说明SM与binder driver之间的关系:

由上可知,service在使用前会先作为client向SM注册;应用若要使用某一个服务,需要先向SM获取该服务的handle,然后通过handle来调用该服务提供的方法。

4.ProcessState

ProcessState是以单例模式设计的。每个进程在使用binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在binder通信时的binder状态。

ProcessState有如下2个主要功能:

1.创建一个thread,该线程负责与内核中的binder模块进行通信,称该线程为Pool thread;

2.为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

4.1 Pool thread

在Binder IPC中,所有进程均会启动一个thread来负责与BD(binder driver)来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍这个类型。

下面是 Pool thread的启动方式: ProcessState::self()->startThreadPool();

4.2 BpBinder获取

BpBinder主要功能是负责client向BD发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据,它的构造函数如下:

BpBinder(int32_t handle);

通过BpBinder的构造函数发现,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标ProcessState通过如下方式来获取BpBinder对象:

ProcessState::self()->getContextObject(handle);

在这个过程中,ProcessState会维护一个BpBinder的vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,回去查询mHandleToObject,如果对应的handle已经有binder指针,那么不再创建,否则创建binder并插入到mHandleToObject中。

ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,client会创建一个代理接口BpServiceManager。

5.IPCThreadState

IPCThreadState也是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool thread,也就是说每一个进程只会启动一个Pool thread,因此每个进程则只需要一个IPCThreadState即可。

Pool thread的实际内容则为:

IPCThreadState::self()->joinThreadPool();

ProcessState中有2个Parcel成员,mIn和mOut,Pool thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中,总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在了mOut中。

ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。

IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。

6.主要基类

6.1基类IInterface

为server端提供接口,它的子类声明了service能够实现的所有的方法;

6.2基类IBinder

BBinder与BpBinder均为IBinder的子类,因此可以看出IBinder定义了binder IPC的通信协议,BBinder与BpBinder在这个协议框架内进行的收和发操作,构建了基本的binder IPC机制。

6.3基类BpRefBase

client端在查询SM获得所需的的BpBinder后,BpRefBase负责管理当前获得的BpBinder实例。

7.两个接口类

7.1 BpINTERFACE

如果client想要使用binder IPC来通信,那么首先会从SM出查询并获得server端service的BpBinder,在client端,这个对象被认为是server端的远程代理。为了能够使client能够想本地调用一样调用一个远程server,server端需要向client提供一个接口,client在在这个接口的基础上创建一个BpINTERFACE,使用这个对象,client的应用能够想本地调用一样直接调用server端的方法。而不用去关心具体的binder IPC实现。

下面看一下BpINTERFACE的原型:

class BpINTERFACE : public BpInterface<IINTERFACE>

顺着继承关系再往上看

template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase

BpINTERFACE分别继承自INTERFACE,和BpRefBase;

● BpINTERFACE既实现了service中各方法的本地操作,将每个方法的参数以Parcel的形式发送给BD。例如BpServiceManager的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
    Parcel data, reply;
    data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
    data.writeString16(name);
    data.writeStrongBinder(service);
    status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
    return err == NO_ERROR ? reply.readExceptionCode() : err;
}

● 同时又将BpBinder作为了自己的成员来管理,将BpBinder存储在mRemote中,BpServiceManager通过调用BpRefBase的remote()来获得BpBinder指针。

7.2 BnINTERFACE

在定义android native端的service时,每个service均继承自BnINTERFACE(INTERFACE为service name)。BnINTERFACE类型定义了一个onTransact函数,这个函数负责解包收到的Parcel并执行client端的请求的方法。

顺着BnINTERFACE的继承关系再往上看, class BnINTERFACE: public BnInterface<IINTERFACE>

IINTERFACE为client端的代理接口BpINTERFACE和server端的BnINTERFACE的共同接口类,这个共同接口类的目的就是保证service方法在C-S两端的一致性。

再往上看 class BnInterface : public INTERFACE, public BBinder

同时我们发现了BBinder类型,这个类型又是干什么用的呢?既然每个service均可视为一个binder,那么真正的server端的binder的操作及状态的维护就是通过继承自BBinder来实现的。可见BBinder是service作为binder的本质所在。

那么BBinder与BpBinder的区别又是什么呢?

其实它们的区别很简单,BpBinder是client端创建的用于消息发送的代理,而BBinder是server端用于接收消息的通道。查看各自的代码就会发现,虽然两个类型均有transact的方法,但是两者的作用不同,BpBinder的transact方法是向IPCThreadState实例发送消息,通知其有消息要发送给BD;而BBinder则是当IPCThreadState实例收到BD消息时,通过BBinder的transact的方法将其传递给它的子类BnSERVICE的onTransact函数执行server端的操作。

8.Parcel

Parcel是binder IPC中的最基本的通信单元,它存储C-S间函数调用的参数.但是Parcel只能存储基本的数据类型,如果是复杂的数据类型的话,在存储时,需要将其拆分为基本的数据类型来存储。

简单的Parcel读写不再介绍,下面着重介绍一下2个函数。

8.1 writeStrongBinder

当一个service 调用add_service把自己加入到SM中时,就会遇到这种情况,如下(IServiceManager.cpp):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 virtual status_t addService(const String16& name, const sp<IBinder>& service,
            bool allowIsolated)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        data.writeInt32(allowIsolated ? 1 : 0);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }

其中writeStrongBinder(Parcel.cpp)如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

接着看flatten_binder:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

    return finish_flatten_binder(binder, obj, out);
}

addService的参数为一个BnINTERFACE类型指针,BnINTERFACE又继承自BBinder:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BBinder* BBinder::localBinder()
    {
        return this;
    }

所以写入到Parcel的binder类型为BINDER_TYPE_BINDER,在SM中,当service的binder类型不为BINDER_TYPE_HANDLE时,SM将不会将此service添加到svclist,但是很显然每个service的添加都是成功的,addService在开始传递的binder类型为BINDER_TYPE_BINDER,SM收到的binder类型为BINDER_TYPE_HANDLE,那么这个过程当中究竟发生了什么?这个问题是这样的,在binder driver中(Binder.c)由以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static void binder_transaction(struct binder_proc *proc,
                   struct binder_thread *thread,
                   struct binder_transaction_data *tr, int reply)
{
..........................................

    if (fp->type == BINDER_TYPE_BINDER)
        fp->type = BINDER_TYPE_HANDLE;
    else
        fp->type = BINDER_TYPE_WEAK_HANDLE;
    fp->handle = ref->desc;
..........................................
}

由之前我们已经知道,SM只是保存了server binder的handle和name,那么当client需要和某个service通讯的时候,如何获得service的binder呢?接着看readStrongBinder

8.2 readStrongBinder

当server端收到client的调用请求之后,如果需要返回一个binder时,可以向BD发送这个binder,当IPCThreadState实例收到这个返回的Parcel时,client可以通过这个函数将这个被server返回的binder读出。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}

再看unflatten_binder:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);

    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

发现如果server返回的binder类型为BINDER_TYPE_BINDER的话,也就是返回一个binder引用的话,直接获取这个binder;如果server返回的binder类型为BINDER_TYPE_HANDLE时,也就是server返回的仅仅是binder的handle,那么需要重新创建一个BpBinder返回给client。

有上面的代码可以看出,SM保存的service的binder仅仅是一个handle,而client则是通过向SM获得这个handle,从而重新构建代理binder与server通信。

这里顺带提一下一种特殊的情况,binder通信的双方即可作为client,也可以作为server.也就是说此时的binder通信是一个半双工的通信。那么在这种情况下,操作的过程会比单工的情况复杂,但是基本的原理是一样的,有兴趣可以分析一下MediaPlayer和MediaPlayerService的例子。

以上就是涉及到binder通讯的一些比较重要的点。关于binder的具体实现就需要查看binder driver的代码了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2015-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员互动联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
HDR in depth
尽管 SDR(标准动态范围)存在诸多弊端和过时的技术流程,但 SDR 格式的视频内容在当今媒体市场中仍处于领先地位, 而 HDR(高动态范围)格式才刚刚开始扩展。在本文中,主要介绍了每种 HDR 格式的最相关信息。所描述的标记使您可以快速深入到 HDR 领域,识别、整合 HDR 内容并解决可能出现的问题。
用户1324186
2021/09/17
2.6K0
HDR关键技术:HEVC/H.265编码优化
与传统标准动态范围(SDR)视频相比,高动态范围(HDR)视频由于比特深度的增加提供了更加丰富的亮区细节和暗区细节。最新的显示技术通过清晰地再现HDR视频内容使得为用户提供身临其境的观看体验成为可能。面对目前日益增长的HDR视频消费需求,研究现有的压缩工具或引入新的技术来高效压缩HDR视频变得十分迫切。本文将介绍有关MPEG及VCEG针对HDR视频压缩的研究进展。
用户1324186
2018/08/08
5.5K0
HDR关键技术:HEVC/H.265编码优化
HDR关键技术:主要标准介绍
HDR是UHD技术中最重要维度之一,带来新的视觉呈现体验。HDR技术涉及到采集、加工、传输、呈现等视频流程上的多个环节,需要定义出互联互通的产业标准,以支持规模化应用和部署。本文整理当前HDR应用中的一些代表性的国际标准。
用户1324186
2018/08/23
6.5K0
HDR关键技术:主要标准介绍
HDR的主要标准有哪些?
HDR ( High-Dynamic Range ) 高动态范围技术是一种在图像处理和显示领域中常用的技术,旨在提供更广泛的亮度范围和更丰富的色彩细节,通过在图像中捕捉和显示更多的亮度级别来提高图像的质量,让电影、图片、游戏画面都能呈现出极佳的效果,使用户在观影、玩游戏时感受更接近真实世界中的视觉体验。
微帧Visionular
2024/10/30
6010
HDR的主要标准有哪些?
HDR标准术语解读
UHD4K的布道师Yoeri Geutskens撰文对各种HDR标准进行了解释,如果你被眼花缭乱的HDR标准搞得一头雾水,本文将会对你有所帮助。 文 / Yoeri Geutskens 译 / 蒋默
LiveVideoStack
2019/09/17
1.7K0
HDR标准术语解读
UHD HDR现状
原标题:The Current State of UHD HDR——A detailed review of the current HDR standards, HDR workflows and state of HDR deployments.
用户1324186
2019/03/07
2.2K0
UHD HDR现状
HDR关键技术:主要标准介绍(续)
前文我们已经对HEVC的HDR编码优化技术和HDR/WCG相关的整体编码方案做了介绍,本文总结几种具有代表性的技术方案,对业内常用的几个HDR分发标准做简要梳理。
用户1324186
2018/08/23
4.3K0
HDR关键技术:主要标准介绍(续)
HDR
LDR SDR HDR简介相机里的HDR视频行业的HDRHDR标准体验真正的HDR参考链接
瓜大三哥
2020/06/09
1.4K0
hysAnalyser --- 支持菁彩视听双Vivid媒体信息解析
本文主要介绍 hysAnalyser 支持HDR Vivid格式的分析案例,满足用户对HDR vivid 和 Audio Vivid 编码格式的分析需要。
hybase
2025/07/04
1120
hysAnalyser --- 支持菁彩视听双Vivid媒体信息解析
西瓜视频是如何实现“端到端HDR”的 | Q推荐
今年 6 月,西瓜视频宣布全面支持 HDR 视频功能,成为首个 HDR 技术覆盖全形态(手机、PC 和平板)、打通全环节(拍摄、编辑和消费)的视频平台。 HDR(High Dynamic Range,高动态范围 ) 视频,相比普通 SDR 视频拥有更高的色深、更广的动态范围和更强的色彩表现力,能显著提升视频画质。当西瓜用户拍摄、编辑、预览、上传和观看 HDR 视频时,字节跳动旗下火山引擎多媒体实验室的“端到端 HDR 视频解决方案”发挥了重要作用,该方案也已逐步开放给火山引擎的企业级客户。 近几年,众多厂
深度学习与Python
2023/04/01
8660
西瓜视频是如何实现“端到端HDR”的 | Q推荐
显示器中的HDR10、HDR400、HDR600有什么区别?
HDR10和HDR400、HDR500、HDR600、HDR1000等看似是类似的概念,都是HDR后面带了一个数字,但实际意义却相差甚远。
微帧Visionular
2024/11/13
12.3K0
显示器中的HDR10、HDR400、HDR600有什么区别?
HDR关键技术—色域映射
HDR系列前几期为大家介绍了HDR的色调映射技术(Tone Mapping)。其中提到:在色调映射环节,为了便于操作,且不使图像颜色产生巨大失真,色调映射算法通常会仅处理图像亮度信息,将HDR图像亮度映射到SDR图像亮度域中,通过原HDR图像的颜色信息,恢复并重建SDR图像的颜色信息。由于前面的主题是色调映射,因此颜色转换相关技术,我们没有深入介绍。但颜色转换或色域映射问题(Color Transfer or Gamut Mapping),也是HDR的重要环节。本文将介绍HDR中颜色转换(或色域映射)技术,分为两个部分,第一部分介绍色域映射的定义以及相关背景知识;第二部分将介绍代表性的色域映射算法,特别对ITU中相关标准进行浅析。
用户1324186
2018/07/26
9.9K0
HDR关键技术—色域映射
HDR关键技术:逆色调映射(一)
HDR技术近年来发展迅猛,在未来将会成为图像与视频领域的主流。当前HDR内容非常短缺,限制了HDR视听节目的广泛应用。逆色调映射(Inverse Tone Mapping)应运而生,它是一种用来将SDR源信号转换为HDR源信号的技术,可以应用于生产端或终端设备,在一定程度上实现对现有SDR节目的HDR“还原”及向上兼容。本系列中,我们将会详细分类介绍逆色调映射算法。分为两个部分:(一)逆色调映射概述及一些经典算法,包括全局算法,分类算法以及拓展映射算法;(二)介绍最近的研究趋势,特别是基于机器学习的逆色调映射算法。Let's go for the first part!
用户1324186
2018/07/26
10.9K0
HDR关键技术:逆色调映射(一)
HDR关键技术:HEVC/H.265编码方案
前文我们对HEVC的HDR编码优化技术做了介绍,侧重编码性能的提升。本章主要阐述HEVC中HDR/WCG相关的整体编码方案,包括不同应用场景下的HEVC扩展编码技术。
用户1324186
2018/08/08
7.6K0
HDR关键技术:HEVC/H.265编码方案
2017 HDR技术动态
2017年是HDR发展突飞猛进的一年,这一年里,HDR不仅仅在技术层面取得了巨大的进步,在消费市场也取得了极大的成功,在其他相关领域中也得到了广泛的应用。 在消费市场上,具备HDR功能的电视无疑已经成为当下的热点,几乎每个主要的电视生产商都推出了数款HDR电视,并且覆盖了多个价位以供消费者选择。事实上,因为HDR技术的不断成熟以及用户对高品质图像显示设备的需求,现在已经很难找到不兼容HDR模式的4K电视了。 随着HDR电视在不断普及,性能评价标准也变得多样了起来,但主要的评价目标仍然是色彩容量。色彩容量
用户1324186
2018/03/05
2.3K0
2017 HDR技术动态
微博HDR视频的落地实践
大家好,我是刘文。目前负责微博客户端播放器的研发。今天我演讲的主题是微博HDR视频的落地实践。
LiveVideoStack
2022/01/05
1.2K0
微博HDR视频的落地实践
【FlatpanelsHD】HDR生态系统追踪器
Dolby Vision被称为Profile 8.4,与基于pq(杜比实验室开发的感知量化技术,也是无处不在的HDR10的基础)的所有其他口味不同,它基于HLG或Hybrid Log Gamma,由BBC和NHK开发,主要用于电视直播。
天天Lotay
2023/10/15
2880
【FlatpanelsHD】HDR生态系统追踪器
航拍 HDR 视频的 VVC 和 AV1 编码
视频产业现在处于一个十字路口,巨大的视频服务行业每年价值约 2000 亿美元。视频占互联网所有流量的 80%,这个比例还在增长。而在这 80% 的流量中,80% 是由 H.264 比特流组成的 -- 这是当今主流的视频编解码器。但 H.264 是在 2003 年实现标准化的,整整 18 年了,现在时机已经成熟,需要一个更新、更强大的编解码器来取代它。
用户1324186
2021/11/15
2.3K0
HDR视频生态系统纵览
Flatpanels作者Yoeri Geutskens对HDR视频生态系统进行了调查并以图表的形式展示。HDR视频图表根据公司业务类型进行分类并通过所使用HDR的格式进行了更详细的划分。LiveV
LiveVideoStack
2021/09/01
6710
2019 HDR生态圈纵览
HDR生态系统规模庞大且不断增长,且已覆盖从生产到交付的全产业链所有部分,但HDR格式在整条产业链的不同端之间存在明显差异。UHD4K的布道师Yoeri Geutskens尝试对HDR生态系统各组成部
LiveVideoStack
2019/07/01
1.1K0
2019 HDR生态圈纵览
相关推荐
HDR in depth
更多 >
LV.3
这个人很懒,什么都没有留下~
目录
  • 1.binder通信机制概述
  • 2.为什么使用binder通信
  • 3.service manager
  • 4.ProcessState
    • 4.1 Pool thread
    • 4.2 BpBinder获取
  • 5.IPCThreadState
  • 6.主要基类
    • 6.1基类IInterface
    • 6.2基类IBinder
    • 6.3基类BpRefBase
  • 7.两个接口类
    • 7.1 BpINTERFACE
    • 7.2 BnINTERFACE
  • 8.Parcel
    • 8.1 writeStrongBinder
    • 8.2 readStrongBinder
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档