平台是RK3066(福州瑞芯微公司),android 4.2.0,其实时VP8硬编码,与软件编码是ffpmeg,x264,xvid等软编码是有区别的。硬编码主要是依赖于
硬件。

  硬编码:通过调用Android系统自带的Camera录制视频,实际上是调用了底层的高清编码硬件模块,也即显卡,不使用CPU,速度快
  软编码:使用CPU进行编码,如常见C/C++代码,一般编译生成的二进制都是的,速度相对较慢。例如使用Android NDK编译H264生成so库,编写jni接口,再使用java调用so库
VPUCoder.h

/*
* VPUCoder.h
*
* Current, Only Support YUV420sp encoder and decoder
*
* Created on: Dec 16, 2013
* Author: henry
*
* Example:
*
* int main()
* {
* int ret = InitCodec();
* //===========encode video
* ret = StartEnc("/sdcard/test.mkv", 1280, 720, 30);
*
* while(1)
* {
* //get data and length, //unsigned char* data; int length
* ret = ProcessEnc(data, length);
* }
* ret = StopEnc();
*
* //===========decode video
* ret = ProcessDec("/sdcard/test.mkv", 1280, 720);
* return 0;
* }
*/ #ifndef VPUCODER_H_
#define VPUCODER_H_ /**
* Init encoder and decoder handle, only call once, must first call
*
* @return 0 is successful, another fail
*/
int InitCodec(); /**
* setup encoder configure
* @param filePath : save file path
* @param enc_width : video width
* @param enc_height : video height
* @param enc_fps : video fps
*
* @return 0 is successful, another fail
*/
int StartEnc(const char* filePath, uint32_t enc_width, uint32_t enc_height, uint32_t enc_fps); /**
* stop encode video
*/
void StopEnc(); /**
* @params data : frame data
* @params length : frame length
*
* @return 0 is successful, another fail
*/
int ProcessEnc(const unsigned char* data, uint32_t length); /**
* setup decoder configure
* @param filePath : source file path
* @param enc_width : video width
* @param enc_height : video height
*
* @return 0 is successful, another fail
*/
int ProcessDec(const char* filePath, uint32_t dec_width, uint32_t dec_height); #endif /* VPUCODER_H_ */

  VPUCoder.cpp

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> #include <vpu_global.h>
#include <SoftwareRenderer.h>
#include <vpu_api_interface.h> #include <utils/Log.h>
#include <ui/DisplayInfo.h>
#include <gui/ISurfaceTexture.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceTextureClient.h>
#include <gui/SurfaceComposerClient.h>
#include <media/stagefright/MetaData.h> using namespace android; #ifdef LOGI
#undef LOGI
#undef LOGW
#undef LOGE
#undef LOGD
#endif #define LOG_TAG_SERVICE "TeliDHVPU8Codec"
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG_SERVICE, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG_SERVICE, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG_SERVICE, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG_SERVICE, __VA_ARGS__) #define MAX_STREM_LENGTH (1280 * 400) static uint32_t g_lenght_enc = MAX_STREM_LENGTH;
static FILE* g_file_enc = NULL;
static FILE* g_file_dec = NULL;
static VPU_API g_vpu_api;
static void* g_vp8encHandle = NULL;
static void* g_vp8decHandle = NULL;
static unsigned int g_bufferLen = 0;
static unsigned char* g_frameBuffer = NULL; static EncParams1 g_encParams;
static int g_SyncFlag = 0;
static unsigned int g_dataSize;
static unsigned int g_InputTimestamp;
static int g_nal = 0;
static int g_ret = 0; int InitCodec()
{
vpu_api_init(&g_vpu_api, OMX_ON2_VIDEO_CodingVPX);
return 0;
} int StartEnc(const char* filePath, uint32_t enc_width, uint32_t enc_height, uint32_t enc_fps)
{
LOGI("StartEnc Begin ====================");
if(!filePath)
{
LOGD("Please make sure file path not null!");
return -1;
} if(g_file_enc)
{
LOGD("Another file is being encoded!");
return -1;
} g_file_enc = fopen(filePath, "wb+");
if(!g_file_enc)
{
LOGD("file open fail!");
return -1;
} g_lenght_enc = enc_width * enc_height * 3 >> 1; memset(&g_encParams, 0, sizeof(EncParams1));
g_encParams.width = enc_width;
g_encParams.height = enc_height;
g_encParams.framerate = 25;
g_encParams.bitRate = 10000; g_frameBuffer = (unsigned char*)malloc(MAX_STREM_LENGTH); g_vp8encHandle = g_vpu_api.get_class_On2Encoder();
g_vpu_api.init_class_On2Encoder(g_vp8encHandle, &g_encParams, g_frameBuffer, &g_bufferLen); g_nal = g_bufferLen;
fwrite(&g_nal, 1, sizeof(g_nal), g_file_enc);
fwrite(g_frameBuffer, 1, g_bufferLen, g_file_enc); LOGI("StartEnc End g_bufferLen = %d ====================", g_bufferLen); return 0;
} void StopEnc()
{
LOGI("StartEnc Begin ====================");
g_lenght_enc = 0;
if(g_frameBuffer)
{
free(g_frameBuffer);
g_frameBuffer = NULL;
} if(g_file_enc)
{
fclose(g_file_enc);
g_file_enc = NULL;
} if(g_vp8encHandle)
{
g_vpu_api.deinit_class_On2Encoder(g_vp8encHandle);
g_vpu_api.destroy_class_On2Encoder(g_vp8encHandle);
g_vp8encHandle = NULL;
}
LOGI("StartEnc End ====================");
} int ProcessEnc(const unsigned char* data, uint32_t length)
{
if(length != g_lenght_enc)
{
LOGD("encode frame length is error!");
StopEnc();
return -1;
} if(!g_file_enc)
{
LOGD("file not open!");
return -1;
} LOGD("enc_oneframe_class_On2AvcEncoder"); g_SyncFlag = 0;
g_ret = g_vpu_api.enc_oneframe_class_On2Encoder(g_vp8encHandle, g_frameBuffer, &g_bufferLen
, (unsigned char*)data, 0, &g_dataSize, &g_InputTimestamp, &g_SyncFlag); if(g_bufferLen > 0 && g_ret >=0)
{
LOGI("ProcessEnc encode one frame ====================");
g_nal = g_bufferLen;
fwrite(&g_nal, 1, sizeof(g_nal), g_file_enc);
fwrite(g_frameBuffer, 1, g_bufferLen, g_file_enc);
fflush(g_file_enc);
}
else
{
LOGD("ProcessEnc encode frame fail!");
return -1;
}
g_bufferLen = 0; return 0;
} int32_t FillFrameHead(unsigned char* dst, unsigned char* src, uint32_t size
, uint32_t bitsreamLen, int64_t time, uint32_t type, uint32_t num)
{
VPU_BITSTREAM h;
uint32_t TimeLow = (uint32_t)(time/1000);
h.StartCode = BSWAP(VPU_BITSTREAM_START_CODE);
h.SliceLength= BSWAP(size);
h.SliceTime.TimeLow = BSWAP(TimeLow);
h.SliceTime.TimeHigh= 0;
h.SliceType= BSWAP(type);
h.SliceNum= BSWAP(num);
h.Res[0] = 0;
h.Res[1] = 0;
memcpy(dst, &h, bitsreamLen); return 0;
} int ProcessDec(const char* filePath, uint32_t dec_width, uint32_t dec_height)
{
LOGI("ProcessDec Begin dec_width = %d dec_height = %d====================", dec_width, dec_height);
if(!filePath)
{
LOGD("src file path is null");
return -1;
} FILE *fp_in = fopen(filePath, "rb");
if(!fp_in)
{
LOGD("File not exist!");
return -1;
} char filePathOut[64];
memset(filePathOut, 0, 64);
sprintf(filePathOut, "%s.yuv", filePath);
g_file_dec = fopen(filePathOut, "wb+"); if(!g_file_dec)
{
LOGD("file open fail!");
fclose(fp_in);
return -1;
} unsigned char* aOutBuffer;
unsigned char* aInputBuf = NULL;
unsigned char* aInputData = NULL;
unsigned int aOutputLength;
unsigned int aInBufSize = MAX_STREM_LENGTH; g_vp8decHandle = g_vpu_api.get_class_On2Decoder();
g_vpu_api.init_class_On2Decoder(g_vp8decHandle); int tmp_length = (dec_width * dec_height * 3) >> 1; LOGI(" init_class_On2AvcDecoder OK! tmp_length=%d", tmp_length); aOutBuffer = (unsigned char*)malloc(tmp_length);
aInputBuf = (unsigned char*)malloc(MAX_STREM_LENGTH); fread(&g_nal, 1, sizeof(g_nal), fp_in); if(g_nal > 0)
{
fread(aInputBuf, 1, g_nal, fp_in);
}
else
{
LOGD("Can't decoder the video!");
goto fail;
} int ret;
uint32_t bitsLen;
uint32_t vpu_stream_lenc; vpu_stream_lenc = sizeof(VPU_BITSTREAM);
aInputData = aInputBuf + vpu_stream_lenc; while(1)
{
ret = fread(&g_nal, 1, sizeof(g_nal), fp_in);
if(ret <= 0)
break; fread(aInputData, 1, g_nal, fp_in);
aInBufSize = g_nal;
bitsLen = vpu_stream_lenc + aInBufSize;
FillFrameHead(aInputBuf, aInputData, aInBufSize, vpu_stream_lenc, 0, 0, 0); ret = g_vpu_api.dec_oneframe_class_On2Decoder(g_vp8decHandle, aOutBuffer, &aOutputLength, aInputBuf, &bitsLen);
LOGI("out_length=%d in_length=%d ret=%d", aOutputLength, bitsLen, ret); if(aOutputLength > 0)
{
VPU_FRAME *frame = (VPU_FRAME *)aOutBuffer; if(frame->vpumem.phy_addr)
{
VPUMemLink(&frame->vpumem); if(frame->vpumem.vir_addr)
{
LOGI("VPUMemLinear_t size=%d", frame->vpumem.size);
fwrite(frame->vpumem.vir_addr, 1, tmp_length, g_file_dec);
fflush(g_file_dec);
}
else
{
LOGI("vir_addr is null");
}
VPUFreeLinear(&frame->vpumem);
}
else
{
LOGI("phy_addr is null");
}
}
fflush(fp_in);
} fail:
if(aOutBuffer)
{
free(aOutBuffer);
aOutBuffer = NULL;
} if(aInputBuf)
{
free(aInputBuf);
aInputBuf = NULL;
} if(g_file_dec)
{
fclose(g_file_dec);
g_file_dec = NULL;
} if(fp_in)
{
fclose(fp_in);
fp_in = NULL;
} if(g_vp8decHandle)
{
g_vpu_api.deinit_class_On2Decoder(g_vp8decHandle);
g_vpu_api.destroy_class_On2Decoder(g_vp8decHandle); g_vp8decHandle = NULL;
}
LOGI("ProcessDec End ===================="); return 0;
}

  android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

VISION=1.0.1

LOCAL_MODULE := VPU8Coder_${VISION}
LOCAL_SRC_FILES := VPUCoder.cpp

LOCAL_LDLIBS := -L$(LOCAL_PATH)/libs \
-lvpu \
-lcutils \
-lutils \
-lgui \
-lrk_on2 \
-lstagefright

LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/include/media/openmax

LOCAL_CFLAGS := -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=

include $(BUILD_SHARED_LIBRARY)

VPU硬编码的更多相关文章

  1. Android安全开发之浅谈密钥硬编码

    Android安全开发之浅谈密钥硬编码 作者:伊樵.呆狐@阿里聚安全 1 简介 在阿里聚安全的漏洞扫描器中和人工APP安全审计中,经常发现有开发者将密钥硬编码在Java代码.文件中,这样做会引起很大风 ...

  2. 使用VideoToolbox硬编码H.264<转>

    文/落影loyinglin(简书作者)原文链接:http://www.jianshu.com/p/37784e363b8a著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. ======= ...

  3. 【Android】Android Camera实时数据采集及通过MediaCodec硬编码编码数据的流程

    吐槽: 其实常用流程都差不多,但是有时候还是会忘记某一步的详细用法,但是各位朋友请注意,官方已经不推荐Camera类的使用(现在是android.hardware.camera2),但无奈公司项目之前 ...

  4. android studio 中查找代码中的硬编码

    在Android Studio中同时按下Ctrl + Shift+ F  或者其他自定义的快捷键,打开全局搜索,在全局搜索中输入 ^((?!(\*|//)).)+[\u4e00-\u9fa5] 并打勾 ...

  5. 【GPU编解码】GPU硬编码

    一.OpenCV中的硬编码 OpenCV2.4.6中,已实现利用GPU进行写视频,编码过程由cv::gpu::VideoWriter_GPU完成,其示例程序如下. int main(int argc, ...

  6. 告别硬编码-发个获取未导出函数地址的Dll及源码

    还在为找内核未导出函数地址而苦恼嘛? 还在为硬编码通用性差而不爽吗? 还在为暴搜内核老蓝屏而痛苦吗? 请看这里: 最近老要用到内核未导出的函数及一些结构,不想再找特征码了,准备到网上找点符号文件解析的 ...

  7. 【流媒体】 Android 实时视频编码—H.264硬编码

    [流媒體] Android 实时视频编码—H.264硬编码 SkySeraph Apr 4th 2012 Email:skyseraph00@163.com 1  硬编码 & 软编码 硬编码: ...

  8. ExpressionTree——让反射性能向硬编码看齐

    缘起 最近又换了工作.然后开心是以后又能比较频繁的关注博客园了.办离职手续的这一个月梳理了下近一年自己写的东西,然后就有了此文以及附带的代码. 反射 关于反射,窃以为,他只是比较慢.在这个前提下,个人 ...

  9. 硬编码写RadioGroup的时候要注意设置RadioButton的Id

    硬编码写RadioGroup的时候要注意RadioButton的id重复问题,导致选择的时候出现能够多选的情况发生,如下代码,注意Id的设置,这样避免Radiobutton的id重复. /** * 生 ...

随机推荐

  1. Lost connection to MySQL server at 'reading authorization packet', system error: 0_Mysql

    1.大多数时候设置"set global connect_timeout=60:"是可以解决问题的. 我们可以通过执行“SHOWSTATUS LIKE 'aborted%'”,可以 ...

  2. 【剑指Offer】40、数组中只出现一次的数字

      题目描述:   一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度为O(n),空间复杂度为O(1).   解题思路:   这道题目相对比较难 ...

  3. 函数(day08)

    C语言里可以采用分组的方式管理语句 每个语句分组叫做一个函数 多函数程序执行的时候时间分配情况必须 遵守以下规则 .整个程序的执行时间被划分成几段,每段 时间都被分配给一个函数使用 .不同时间段不能互 ...

  4. layui 导出excel复杂表头

    众所周知 layui的导出功能很好用,但是今天我要给大家推荐一个更好用的 大家来到这里想必也是因为layui无法满足 [导出Excle复杂表头] 的业务需求而来,这里废话不多说但还是强调一点,如果你是 ...

  5. NET 爬虫

    最近经常听说或者接触关于网络爬虫的问题,只是一直看到被人写的代码.而没有真正的做过实践, 昨天做了一下尝试,其中采用网络流行的扩展类库 http://html-agility-pack.net/?z= ...

  6. daemon not running; starting now at tcp:5037 adb: CreateFileW 'nul' failed: 系统找不到指定的文件

    1. INFO - roid.tools.idea.adb.AdbService - Initializing adb using: C:\Users\Administrator\AppData\Lo ...

  7. docker 容器操作( 以 tomcat 为例 )

    一.容器操作 一个镜像可以启动多个容器.比如一个 tomcat 镜像,可以启动多个tomcat 容器,启动后的这些 tomcat 都是各自独立的 二.步骤 1.搜索镜像 [root@localhost ...

  8. TotoiseSVN使用教程

    TortoiseSVN百科 TortoiseSVN 是 Subversion 版本控制系统的一个免费开源客户端,可以超越时间的管理文件和目录.文件保存在中央版本库,除了能记住文件和目录的每次修改以外, ...

  9. Ada boost学习

    http://blog.csdn.net/dark_scope/article/details/14103983 据说在Deep Learning出来之前,SVM和Adaboost是效果最好的 两个算 ...

  10. TensorFlow 入门之手写识别CNN 三

    TensorFlow 入门之手写识别CNN 三 MNIST 卷积神经网络 Fly 多层卷积网络 多层卷积网络的基本理论 构建一个多层卷积网络 权值初始化 卷积和池化 第一层卷积 第二层卷积 密集层连接 ...