VPU hard-coded and VPU-encoded
The platform is RK3066 (Fuzhou ruixin microcompany), android 4.2.0, and its real-time VP8 hard code, which is different from software coding such as ffpmeg, x264, and xvid. Hard coding mainly depends on
Hardware.
Hard coding: by calling the Camera recording video that comes with the Android system, it actually calls the underlying HD encoding hardware module, that is, the video card, which does not use the CPU and is fast.
Soft encoding: the CPU is used for encoding, such as common C/C ++ code. Generally, the binary data generated by compilation is of a low speed. For example, use Android NDK to compile H264 to generate the so library, write the jni interface, and then use java to call the so library.
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)
What is hard encoding?
Hard coding is a code solution that is not flexible enough.
For example, a program in a service period needs to create a server for listening during execution. You can simply put the port number to be listened to in the code or pass in through program parameters, you can also place it in the configuration file.
The above code is called hard encoding.
Q: What is hard encoding? What is the difference between hard encoding and normal encoding?
For example, if you make a software program and have a menu bar, if you write all the menu titles in the code, you have to change the code if you want to change English.
Replace the corresponding value in the token with English.
You do not need to go to the Code itself.
This is the concept of separation from configuration.
Also, for example, the concept of interface-oriented programming, you can go online to check, which can reduce the post-maintenance caused by hard encoding.