android下mjpeg格式硬解码

本帖最后由 linan 于 2014-12-5 17:09 编辑

大家好,新手发问!
我现在获取到mjpeg格式的数据流,想通过硬解码的方式,转换为YUV420格式,这个有办法吗?
我的数据流为摄像头获取的,分辨率1280x720,30fps,通过软件转码的方式,效率较低。
请大家多多指教!

楼主有没有试过mediacodec这个安卓类库。

error结构体 发表于 2014-12-5 18:46
楼主有没有试过mediacodec这个安卓类库。

首先谢谢版主的答复!我用过mediacode类,但在平台中,其启动的mediaserver服务占用cpu太多,所以想直接调用RK3288硬解码mjpeg的库,提高应用效率。

软件解很占 cpu ? 测试纯软件解 1920x1080 的 h264, 可以到 20fps. mjpeg 算法很简单的和h264 比不是一个数量级的

版主,您好!我现在也在研究Mjpeg硬解码,但一直没有头绪…您能帮忙提供资料吗?

请问用skia的SkJPEGImageDecoder::onDecode接口测试过吗?

mjpeg格式硬解码楼主有做完吗?能否提供Demo给我参考?hw_jpeg_decode参数不会传呀!

可以参考这个文件frameworks/base/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp,这里面调用的libskia.so,libskia里调用的硬解码接口hw_jpeg_decode

q373149369 发表于 2015-7-6 10:38
版主,您好!我现在也在研究Mjpeg硬解码,但一直没有头绪…您能帮忙提供资料吗?

你好,MJPEG硬解码的问题解决了么?

q373149369 发表于 2015-7-13 15:36
mjpeg格式硬解码楼主有做完吗?能否提供Demo给我参考?hw_jpeg_decode参数不会传呀!

你好,MJPEG硬解码的问题解决了么?

你好,MJPEG硬解码的问题解决了么?

有没有人在啊

用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

insighters 发表于 2018-6-21 17:50
用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

我的3288 android 5.1.1用jpeg编解码库是libjpeghwdec.so和libjpeghwenc.so。请问你那边是什么?

insighters 发表于 2018-6-21 17:50
用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

我的3288 android 5.1.1用jpeg编解码库是jpeghwdec和jpeghwenc。请问你那边是什么?

insighters 发表于 2018-6-21 17:50
用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

我的3288 android 5.1.1用jpeg编解码库是什么?

insighters 发表于 2018-6-21 17:50
用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

你好,请问有参考demo吗?

insighters 发表于 2018-6-21 17:50
用硬解实现了,但发现效率不高啊,memcpy也比较消耗时间

大牛,有参考的demo吗,小弟这边也想用vpu 硬解JPEG,求分享

附件需要在android目录下编译,生成的so可以在ndk使用,支持yuyv/nv12/rgba3种格式

external/skia也需要略作修改
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 43c3c8c..eb504bb 100755
— a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -351,6 +351,7 @@ public:
virtual size_t getLength() const SK_OVERRIDE;

 virtual const void* getMemoryBase() SK_OVERRIDE;
  •   virtual bool markSupport() SK_OVERRIDE;
    

private:
SkData* fData;
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index ceb30d5..2972343 100755
— a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -314,6 +314,7 @@ static SkData* newFromParams(const void* src, size_t size, bool copyData) {
}
}

SkMemoryStream::SkMemoryStream() {
fData = SkData::NewEmpty();
fOffset = 0;
@@ -343,6 +344,12 @@ SkMemoryStream::~SkMemoryStream() {
fData->unref();
}

+bool SkMemoryStream::markSupport(){

  • //for show whether support reset() or mark() in java, add by WH
  • return true;
    +}

void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
fData->unref();
fData = SkData::NewFromMalloc(src, size);
diff --git a/src/images/SkHwJpegUtility.cpp b/src/images/SkHwJpegUtility.cpp
index 9c7b434..5e9c5ae 100755
— a/src/images/SkHwJpegUtility.cpp
+++ b/src/images/SkHwJpegUtility.cpp
@@ -13,13 +13,16 @@

  • See the License for the specific language governing permissions and
  • limitations under the License.
    */

+//#define DEBUG_HW_JPEG
#include “SkHwJpegUtility.h”
#include “SkCanvas.h”
#ifdef DEBUG_HW_JPEG
#include “utils/Log.h”
#undef LOG_TAG
#define LOG_TAG “SkHwJpegUtility”
-#define WHLOG LOGE
+#define WHLOG ALOGD
+#define WHREDLOG ALOGE
#endif

/////////////////////////////////////////////////////////////////////
@@ -514,6 +517,7 @@ SkJpegVPUMemStream::SkJpegVPUMemStream(SkStream * stream, size_t *len){
hw_jpeg_VPUMallocLinear(&vpuMem, mallocSize);
if(vpuMem.vir_addr != NULL)
{

  •           WHLOG("SkJpegVPUMemStream virtual addr: %p ", vpuMem.vir_addr);
              stream->rewind();
              bool readApp1 = false, readApp0 = false, readSof = false, error = false;
              unsigned short twoBytes = 0;
    

@@ -524,7 +528,7 @@ SkJpegVPUMemStream::SkJpegVPUMemStream(SkStream * stream, size_t *len){
break;
}
size_t readBytes = stream->read(&twoBytes,2);//FIX ME if big edian

  •                   WHLOG("meet mark : 0x%x, readBytes: %d", twoBytes, readBytes);
    
  •                   WHLOG("meet mark : 0x%x, readBytes: %d, bytesInStream:%d", twoBytes, readBytes, bytesInStream);
                      error = (readBytes<=0);
                      if(error){
                              break;
    

@@ -533,6 +537,10 @@ SkJpegVPUMemStream::SkJpegVPUMemStream(SkStream * stream, size_t *len){
memcpy(mem, &twoBytes, sizeof(unsigned short));
mem += readBytes;
switch(twoBytes){

  •                           case 0xDAFF:
    
  •                                   readApp1 = true;
    
  •                                   readApp0 = true;
    
  •                                   break;
                              case 0xD9FF://EOI
                                      readApp1 = true;
                                      readApp0 = true;
    

@@ -546,6 +554,8 @@ SkJpegVPUMemStream::SkJpegVPUMemStream(SkStream * stream, size_t *len){
case 0xC2FF://SOF2
if(twoBytes == 0xC0FF || twoBytes == 0xC2FF){
readSof = true;

  •                                           //fix error
    
  •                                           //readApp0 = true;
                                      } else if(twoBytes == 0xE0FF){
                                              readApp0 = true;
                                      }else if(twoBytes == 0xE1FF){
    

diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 003a77e..a8513c1 100755
— a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -30,7 +30,9 @@ extern “C” {
#include “jerror.h”
}

-//#define HW_JPEG_DEBUG
+//extern “C” void *memcpy_kernel(void *dest, const void *src, size_t n);
+
+#define HW_JPEG_DEBUG
#ifdef HW_JPEG_DEBUG
#define HW_DEBUG SkDebugf
#else
@@ -596,6 +598,7 @@ do{
if (SkImageDecoder::kDecodeBounds_Mode != mode) {
//use hardvpu mem sometimes when it is not decodeBounds_Mode
bool markSupport = stream->markSupport();

  •                   //markSupport = true;
                      WHLOG("markSupport: %d", markSupport);
                      if(markSupport){//only markSupport and not justcalwh
    

#ifdef WH_DEBUG_JPEG
@@ -613,6 +616,7 @@ do{
goto __SOFT_DEC;
}
}
+
HwJpegInputInfo hwInfo;
HwJpegOutputInfo outInfo;
hwInfo.justcaloutwh = SkImageDecoder::kDecodeBounds_Mode != mode? 0:1;
@@ -650,6 +654,8 @@ do{
if(reuseBitmap > 0 && colorType != bm->colorType()){
HW_DEBUG(“bitmap is not null, but its config is not according with require.”);
}
+

  •           HW_DEBUG("bitmap width:%d, height:%d, rowptr:%p", bm->width(), bm->height(), rowptr);
              if(hw_jpeg_decode(&hwInfo,&outInfo, &reuseBitmap, bm->width(), bm->height()) >= 0){
                      if(reuseBitmap < 0){
                          HW_DEBUG("REUSE BITMAP FAILED.");
    

@@ -680,9 +686,10 @@ do{
JSAMPLE * rowptr = (JSAMPLE*)bm->getPixels();
char *srcAddr = outInfo.outAddr;
HW_DEBUG(“bpr: %d, rowptr: %x, srcAddr: %x, reuseBitmap: %d\n”,bpr, rowptr, srcAddr, reuseBitmap);

  •                           WHLOG("bpr: %d, rowptr: %x, srcAddr: %x",bpr, rowptr, srcAddr);
    
  •                           HW_DEBUG("bpr: %d, rowptr: %x, srcAddr: %x, ppscale width:%d\n",bpr, rowptr, srcAddr);
                              while(height < outInfo.outHeight){
                                      memcpy(rowptr, srcAddr, bpr);
    
  •                                   //memcpy_kernel(rowptr, srcAddr, bpr);
                                      rowptr += bpr;
                                      srcAddr += outInfo.ppscalew * pixelBytes;
                                      height++;
    

jpegHwDecode.zip (2.29 KB)

使用示例
bool ret = JpegHwDecoder::decode((char *) jpeg->data, jpeg->data_bytes, (char *) rgba->data,
JpegHwDecoder::RGBA, &width, &height, false);
JpegHwDecoder::RGBA, &width, &height, false);