Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92

编解码器注册:

SKIA的编解码部分通过一个模板类来实现,这样做的为了实现不同类型的codec兼容
external\skia\include\core\SkTRegistry.h

template <typename T> class SkTRegistry : SkNoncopyable {
public:typedef T Factory;//fFact即传进去来的fact类型,其实它是一个函数指针,后面创建codec会调用。explicit SkTRegistry(T fact) : fFact(fact) {
#ifdef SK_BUILD_FOR_ANDROID// work-around for double-initialization bug{//gHead是链表头SkTRegistry* reg = gHead;//循环比较每个元素while (reg) {//找到就返回if (reg == this) {return;}//比较下一个reg = reg->fChain;}}
#endif//没有找到则说明是没注册过fChain = gHead;//当前最新注册作为表头gHead  = this;}static const SkTRegistry* Head() { return gHead; }const SkTRegistry* next() const { return fChain; }const Factory& factory() const { return fFact; }
};

模板类被定义成如下type:
SkImageDecoder.h

typedef SkTRegistry<SkImageDecoder*(*)(SkStreamRewindable*)>        SkImageDecoder_DecodeReg;
typedef SkTRegistry<SkImageDecoder::Format(*)(SkStreamRewindable*)> SkImageDecoder_FormatReg;

SkImageEncoder.h

typedef SkTRegistry<SkImageEncoder*(*)(SkImageEncoder::Type)> SkImageEncoder_EncodeReg;

调用例子,比如jpeg编解码模块的使用:
SkImageDecoder_libjpeg.cpp

static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);

参数factory这样就被注册到末班的链表中了,供后面创建调用。


创建:

只看解码部分
SkImageDecoder_FactoryRegistrar.cpp

SkImageDecoder* image_decoder_from_stream(SkStreamRewindable* stream) {SkImageDecoder* codec = NULL;//取出链表头const SkImageDecoder_DecodeReg* curr = SkImageDecoder_DecodeReg::Head();//循环调用每个解码器while (curr) {//获取的是fFact,而我们的factory实现就是赋值给它的//根据stream来判断能否找到对应的codeccodec = curr->factory()(stream);//找到就返回if (codec) {return codec;}//不适合就继续看下一个codec是否符合curr = curr->next();}return NULL;
}

继续拿jpeg当调用例子,curr->factory()对应的就是sk_libjpeg_dfactory(),
SkImageDecoder_libjpeg.cpp

static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {//先判断stream是不是jpeg流if (is_jpeg(stream)) {//SkNEW其实就是new的实现return SkNEW(SkJPEGImageDecoder);}return NULL;
}

这样其实就是创建了类SkJPEGImageDecoder


编解码

编解码部分必须要子类实现:
SkImageDecoder.h

    // must be overridden in subclasses. This guy is called by decode(...)virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0;

还是拿JPEG为例

bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode){#ifdef USE_HW_JPEGSkStream *thumbStream = NULL;SkJpegVPUMemStream *vpuStream = NULL;ReusePmem thumbPmem; //if hw decode thumbnail, reuse the thumb data in pmem, do not malloc vmthumbPmem.reuse = 0;AutoScaleBitmap thumbBitmap;HW_DEBUG("JPEG HW Decode!");
do{
......if (SkImageDecoder::kDecodeBounds_Mode != mode) {//use hardvpu mem sometimes when it is not decodeBounds_Modebool markSupport = stream->markSupport();markSupport = true;HW_DEBUG("markSupport: %d", markSupport);if(markSupport){//only markSupport and not justcalwh
#ifdef WH_DEBUG_JPEGAutoTimeMillis atm("JPEG read stream.");
#endif//should change to mark a new value for stream?vpuStream = new SkJpegVPUMemStream(stream, &streamlen);if(vpuStream->getLength() <= 0){HW_DEBUG("VPU STREAM LENGTH less than ZERO!");break;}stream = vpuStream;} else {HW_DEBUG("===========goto jpeg soft decode,need to debug=======");goto __SOFT_DEC;}}HwJpegInputInfo hwInfo;HwJpegOutputInfo outInfo;hwInfo.justcaloutwh = SkImageDecoder::kDecodeBounds_Mode != mode? 0:1;outInfo.thumbPmem = &thumbPmem;int pixelBytes = -1;sk_hw_jpeg_source_mgr sk_hw_stream(stream,this,&hwInfo,vpuStream != NULL);hwInfo.streamCtl.inStream = &sk_hw_stream;hwInfo.streamCtl.wholeStreamLength = streamlen;// > 64M? break;HW_DEBUG("Stream length: %d", hwInfo.streamCtl.wholeStreamLength);hwInfo.streamCtl.thumbOffset = -1;hwInfo.streamCtl.thumbLength = -1;hwInfo.streamCtl.useThumb = 0;PostProcessInfo * ppInfo = &hwInfo.ppInfo;
......if(hw_jpeg_decode(&hwInfo,&outInfo, &reuseBitmap, bm->width(), bm->height()) >= 0){if(reuseBitmap < 0){HW_DEBUG("REUSE BITMAP FAILED.");if(vpuStream != NULL){delete vpuStream;}return false;}
......}
}while(0);
#endif
__SOFT_DEC:
......int status = jpeg_read_header(&cinfo, true);if (status != JPEG_HEADER_OK) {#ifdef USE_HW_JPEGRELEASE_STREAM;#endifreturn return_false(cinfo, *bm, "read_header");}......if (!jpeg_start_decompress(&cinfo)) {
......#ifdef USE_HW_JPEGRELEASE_STREAM;#endifreturn tmp;} else {#ifdef USE_HW_JPEGRELEASE_STREAM;#endifreturn return_false(cinfo, *bm, "start_decompress");}}sampleSize = recompute_sampleSize(sampleSize, cinfo);......jpeg_finish_decompress(&cinfo);#ifdef USE_HW_JPEGRELEASE_STREAM;#endifreturn true;}

虽然次函数对soft/hard decode都有做实现,但是发现写死了(stream->markSupport()直接返回false)是soft decoder,不明白是什么原因。


参考:

Android图片编解码实现方案(Skia) demo

[RK3288][Android6.0] Skia中的编解码小结相关推荐

  1. [RK3288][Android6.0] 设置中通过Sensor旋转显示画面小结

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 Settings -> Display有个选项控制旋转屏幕时内容是否跟着旋转 这个功能是通过 ...

  2. Skia深入分析6——skia中图像编解码代码概述

    1.API和自注册机制 Skia中编码解码图片都只需要一行代码: SkBitmap bitmap; SkImageDecoder::DecodeFile("test.xxx", & ...

  3. 声道切换 android,[RK3288][Android6.0] Audio中的单声道到双声道的转换处理过程

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 播放音乐是单声道,硬件用的是双声道. AudioFlinger::PlaybackThread:: ...

  4. [RK3288][Android6.0] Audio中的单声道到双声道的转换处理过程

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 播放音乐是单声道,硬件用的是双声道. AudioFlinger::PlaybackThread:: ...

  5. android开启热点softap模式,[RK3288][Android6.0] Wifi开启热点(SoftAP)流程小结

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 在Settings中选择要打开wifi热点功能: 调用流程如下: onPreferenceChan ...

  6. android apk旋转,[RK3288][Android6.0] Apk设置显示旋转过程小结

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 setRequestedOrientation -> Activity.java Activ ...

  7. [RK3288][Android6.0] Audio的音量设置流程小结

    Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 说明一: AudioManager提供了两个调节音量接口 adjustSuggestedStrea ...

  8. HDMI/DVI中TMDS编解码算法的理解

    HDMI/DVI中TMDS编解码算法的理解 TMDS简介 TMDS编码 TMDS解码 TMDS简介 HDMI和DVI协议使用TMDS作为它们的物理层.支持高达225MHz的传输速率,一个传输链路能满足 ...

  9. Android系统(127)---Android6.0存储中加入总内存和系统内存项和在西语下把,换成.

    Android6.0存储中加入总内存和系统内存项 阅读数:651 平台下patches/packages/apps/Settings/里面 1.存储中加入总内存和系统内存项 在 res/values- ...

最新文章

  1. 「机器学习」机器学习算法优缺点对比(汇总篇)
  2. Apache+PHP配置过程详解
  3. 不能创建Outlook邮件的解决办法
  4. 使用NLog实现一个简单的日志记录(包含源代码)
  5. 时问轴php,php-发布到时间轴-过去的日期
  6. C#抽象类与接口的区别【转】
  7. POJ-3281-Dining(求一对二最大匹配数/最大流)
  8. break和continue-break代码演练
  9. python 中的static-method (静态函数), classmethod(类函数 ), 成员函数
  10. 【leetcode】Combinations (middle)
  11. 两分数相乘后约分的Cantor表(洛谷P1482题题解,Java语言描述)
  12. java mysql 版本查询_如何查看数据库版本
  13. 初中物理凸透镜成像动态图_中考物理考点知识总复习:探究凸透镜成像规律
  14. webpack5的tree-shaking值得了解
  15. druid 手动指定数据源_Spring Boot2 系列教程(二十)整合JdbcTemplate 多数据源
  16. 再述:python中redis的使用(Pool)
  17. 如何快速找到微信支付的商户号和商户密钥?望相互转告!
  18. iphone个系列尺寸_iphone各机型尺寸
  19. oa处理会签流程图_关于合同会签OA流程使用说明
  20. 《平凡的世界》文摘----少安写给她妹妹的那封信...

热门文章

  1. 安静:内向性格的竞争力 苏珊·凯恩
  2. 中山大学数据科学与计算机学院复试分数线,2019中山大学数据科学与计算机学院考研复试分数线...
  3. not attached to activity
  4. web服务器—nginx
  5. 微信公众号获取的封面图片显示‘’此图片来自微信公众平台,未经允许不可引用'的解决方案
  6. google账号已停用,此账号的使用方式似乎违反了Google的政策
  7. python的文件读写方法有哪些_python读写文件的方法有哪些
  8. 计算机网络-MAC地址与以太网帧格式
  9. 如何写好JAVA代码
  10. 风林评《解读基金,我的投资观与实践》|你怎么能不知道基金投资的三个思想...