FFMEPG 平台移植,接口简化和外部模块接入 (三)ffmpeg android移植(ffmpeg实现水印文字显示)

Stella981
• 阅读 814

首先来看一副图,用来纪念对视频领域做出贡献的雷神:

FFMEPG 平台移植,接口简化和外部模块接入 (三)ffmpeg android移植(ffmpeg实现水印文字显示)

当然在这个图片里面的decode不是必须的,Filter 模块本身是一个非常独立的模块,但因为相关的程序,给人造成了他必须要依赖于decoder或者encoder来工作。

OK 不多说,先看看内部实现代码:

[cpp] view plain copy

  1. #ifndef __CAREYE_PUBLIC_H__  

  2. #define __CAREYE_PUBLIC_H__  

  3. #define __STDC_CONSTANT_MACROS  

  4. #ifdef _WIN32  

  5. #define CE_API  __declspec(dllexport)  

  6. #define CE_APICALL  __stdcall  

  7. #else  

  8. #define CE_API  

  9. #define CE_APICALL   

  10. #endif  

  11. #ifndef _WIN32  

  12. #define _ANDROID_  

  13. #endif  

  14. #ifdef _ANDROID_  

  15. #include <android/log.h>  

  16. #define CarEyeLog(...) __android_log_print(ANDROID_LOG_DEBUG, "Car-eye-ffmpeg", __VA_ARGS__)  

  17. #else  

  18. #define CarEyeLog   printf  

  19. #endif  

  20. typedef struct _CarEye_YUVFrame_  

  21. {  

  22.     // Y分量数据存储区  

  23.     unsigned char *Y;  

  24.     // Y分量数据字节数  

  25.     int YSize;  

  26.     // U分量数据存储区  

  27.     unsigned char *U;  

  28.     // U分量数据字节数  

  29.     int USize;  

  30.     // V分量数据存储区  

  31.     unsigned char *V;  

  32.     // V分量数据字节数  

  33.     int VSize;  

  34. }CarEye_YUVFrame;  

  35. //error number  

  36. #define NO_ERROR                    0  

  37. #define PARAMTER_ERROR      1  

  38. #define NULL_MEMORY             2  

  39. #define MAX_FILTER_DESCR 512  

  40. #endif

  

[cpp] view plain copy

  1. #ifndef __CAREYE_FILTER_INTERFACE_H__  

  2. #define __CAREYE_FILTER_INTERFACE_H__  

  3. #define MAX_STRING_LENGTH 1024  

  4. #define MAX_FILE_NAME 64  

  5. // OSD水印结果定义  

  6. typedef struct _CarEye_OSDParam_  

  7. {  

  8.     int width;  

  9.     int height;  

  10.     int fps;  

  11.     // 起始X轴坐标  

  12.     int X;  

  13.     // 起始Y轴坐标  

  14.     int Y;  

  15.     // 字体大小  

  16.     int FontSize;  

  17.     // 16进制的RGB颜色值,如绿色:0x00FF00  

  18.     unsigned int FontColor;  

  19.     // 水印透明度 0~1  

  20.     float Transparency;  

  21.     // 水印内容  

  22.     char SubTitle[MAX_STRING_LENGTH];  

  23.     // 字体名称,字体文件放到库的同目录下,如“arial.ttf”  

  24.     char FontName[MAX_FILE_NAME];  

  25. }CarEye_OSDParam;  

  26. typedef struct  

  27. {  

  28.     AVFrame *VFrame;  

  29.     // 编码后的音频帧    

  30.     CarEye_OSDParam para;  

  31.     void* handle;  

  32. }CarEyeFilter;  

  33. #ifdef __cplusplus  

  34. extern "C"  

  35. {  

  36. #endif  

  37.     /* 

  38.     * Comments: 打开水印资源 

  39.     * Param aEncoder: 编码器对象句柄 

  40.     * Param aParam: 水印参数 

  41.     * @Return int 是否成功,0成功,其他失败 

  42.     */  

  43.     CE_API int CE_APICALL CarEye_OpenOsd(CarEyeFilter* pFilter, CarEye_OSDParam aParam);  

  44.     /* 

  45.     * Comments: 关闭水印资源 

  46.     * Param aDeocoder: 编码器对象 

  47.     * @Return int 关闭成功与否 0成功 

  48.     */  

  49.     CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFilter);  

  50.     CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFilter, CarEye_YUVFrame *aYuv, CarEye_OSDParam aParam);  

  51. #ifdef __cplusplus  

  52. }  

  53. #endif  

  54. #endif

  

实现部分代码:

[cpp] view plain copy

  1. #include "FFVideoFilter.h"  

  2. /* 

  3. * Comments: 打开水印资源 

  4. * Param aEncoder: 编码器对象句柄 

  5. * Param aParam: 水印参数 

  6. @Return int 是否成功,0成功,其他失败 

  7. */  

  8. CE_API int CE_APICALL CarEye_OpenOsd( CarEyeFilter* pFliter, CarEye_OSDParam aParam)  

  9. {  

  10.     if(pFliter==NULL)  

  11.     {  

  12.         return -PARAMTER_ERROR;  

  13.     }  

  14.     avfilter_register_all();  

  15.     pFliter->VFrame = NULL;  

  16.     pFliter->VFrame = av_frame_alloc();  

  17.     if(pFliter->VFrame ==   NULL)  

  18.     {         

  19.         return -NULL_MEMORY;  

  20.     }         

  21.     pFliter->VFrame->width = aParam.width;  

  22.     pFliter->VFrame->height = aParam.height;  

  23.     pFliter->VFrame->pts = 0;   

  24.     if (av_image_alloc(pFliter->VFrame->data, pFliter->VFrame->linesize,  

  25.     pFliter->VFrame->width,  pFliter->VFrame->height,  

  26.     AV_PIX_FMT_YUV420P, 16) < 0)  

  27.     {  

  28.         CarEyeLog("Cannot av_image_alloc\n");  

  29.         av_frame_free(&pFliter->VFrame);  

  30.         return -NULL_MEMORY;  

  31.     }  

  32.     pFliter->VFrame->format = AV_PIX_FMT_YUV420P;  

  33.     FFVideoFilter *handle = new FFVideoFilter();  

  34.     pFliter->handle =(FFVideoFilter*)handle;   

  35.     return handle->InitFilters( aParam);  

  36. }  

  37. CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFliter, CarEye_YUVFrame *aYuv,CarEye_OSDParam param)  

  38. {  

  39.     if(pFliter==NULL || pFliter->VFrame == NULL)  

  40.     {  

  41.           return -PARAMTER_ERROR;  

  42.     }     

  43.     FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;  

  44.       pFliter->VFrame->pts++;  

  45.       memcpy(pFliter->VFrame->data[0], aYuv->Y, aYuv->YSize);  

  46.     memcpy(pFliter->VFrame->data[1], aYuv->U, aYuv->USize);  

  47.     memcpy(pFliter->VFrame->data[2], aYuv->V, aYuv->VSize);         

  48.     if (handle->BlendFilters(pFliter->VFrame,param) < 0)  

  49.     {         

  50.         return -PARAMTER_ERROR;  

  51.     }  

  52.     memcpy(aYuv->Y, pFliter->VFrame->data[0], aYuv->YSize);  

  53.     memcpy(aYuv->U, pFliter->VFrame->data[1],  aYuv->USize);  

  54.     memcpy(aYuv->V, pFliter->VFrame->data[2],  aYuv->VSize);  

  55.     return NO_ERROR;  

  56. }  

  57. /* 

  58. * Comments: 关闭水印资源 

  59. * Param aDeocoder: 编码器对象 

  60. @Return int 关闭成功与否 0 成功 

  61. */  

  62. CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFliter)  

  63. {  

  64.     FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;  

  65.   if(pFliter->VFrame != NULL)  

  66.   {  

  67.       av_frame_free(&pFliter->VFrame);  

  68.   }  

  69.     delete handle;  

  70.     return NO_ERROR;

  

[cpp] view plain copy

  1. #include "FFVideoFilter.h"  

  2. /* 

  3. * Comments: 打开水印资源 

  4. * Param aEncoder: 编码器对象句柄 

  5. * Param aParam: 水印参数 

  6. @Return int 是否成功,0成功,其他失败 

  7. */  

  8. CE_API int CE_APICALL CarEye_OpenOsd( CarEyeFilter* pFliter, CarEye_OSDParam aParam)  

  9. {  

  10.     if(pFliter==NULL)  

  11.     {  

  12.         return -PARAMTER_ERROR;  

  13.     }  

  14.     avfilter_register_all();  

  15.     pFliter->VFrame = NULL;  

  16.     pFliter->VFrame = av_frame_alloc();  

  17.     if(pFliter->VFrame ==   NULL)  

  18.     {         

  19.         return -NULL_MEMORY;  

  20.     }         

  21.     pFliter->VFrame->width = aParam.width;  

  22.     pFliter->VFrame->height = aParam.height;  

  23.     pFliter->VFrame->pts = 0;   

  24.     if (av_image_alloc(pFliter->VFrame->data, pFliter->VFrame->linesize,  

  25.     pFliter->VFrame->width,  pFliter->VFrame->height,  

  26.     AV_PIX_FMT_YUV420P, 16) < 0)  

  27.     {  

  28.         CarEyeLog("Cannot av_image_alloc\n");  

  29.         av_frame_free(&pFliter->VFrame);  

  30.         return -NULL_MEMORY;  

  31.     }  

  32.     pFliter->VFrame->format = AV_PIX_FMT_YUV420P;  

  33.     FFVideoFilter *handle = new FFVideoFilter();  

  34.     pFliter->handle =(FFVideoFilter*)handle;   

  35.     return handle->InitFilters( aParam);  

  36. }  

  37. CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFliter, CarEye_YUVFrame *aYuv,CarEye_OSDParam param)  

  38. {  

  39.     if(pFliter==NULL || pFliter->VFrame == NULL)  

  40.     {  

  41.           return -PARAMTER_ERROR;  

  42.     }     

  43.     FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;  

  44.       pFliter->VFrame->pts++;  

  45.       memcpy(pFliter->VFrame->data[0], aYuv->Y, aYuv->YSize);  

  46.     memcpy(pFliter->VFrame->data[1], aYuv->U, aYuv->USize);  

  47.     memcpy(pFliter->VFrame->data[2], aYuv->V, aYuv->VSize);         

  48.     if (handle->BlendFilters(pFliter->VFrame,param) < 0)  

  49.     {         

  50.         return -PARAMTER_ERROR;  

  51.     }  

  52.     memcpy(aYuv->Y, pFliter->VFrame->data[0], aYuv->YSize);  

  53.     memcpy(aYuv->U, pFliter->VFrame->data[1],  aYuv->USize);  

  54.     memcpy(aYuv->V, pFliter->VFrame->data[2],  aYuv->VSize);  

  55.     return NO_ERROR;  

  56. }  

  57. /* 

  58. * Comments: 关闭水印资源 

  59. * Param aDeocoder: 编码器对象 

  60. * @Return int 关闭成功与否 0 成功 

  61. */  

  62. CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFliter)  

  63. {  

  64.     FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;  

  65.   if(pFliter->VFrame != NULL)  

  66.   {  

  67.       av_frame_free(&pFliter->VFrame);  

  68.   }  

  69.     delete handle;  

  70.     return NO_ERROR;  

  71. }

  

在写JNI之前先看下make文件,主要有两个,android.mk用来实现对ffmpeg 库和新增加的外部水印库的编译,application.mk 主要定义编译的全局变量,如参数和架构等,看下怎么编译ffmpeg的动态库的,这里我们没有用到FFMPEG的avdevice这个库。

#APP_ABI := armeabi armeabi-v7a x86 ifeq ($(APP_ABI), x86) LIB_NAME_PLUS := x86 else LIB_NAME_PLUS := armeabi endif

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS) LOCAL_MODULE:= avcodec-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavcodec-57.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE:= avfilter-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavfilter-6.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE:= avformat-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavformat-57.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := avutil-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libavutil-55.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := swresample-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswresample-2.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) LOCAL_MODULE := swscale-prebuilt-$(LIB_NAME_PLUS) LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswscale-4.so include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS) ifeq ($(APP_ABI), x86) TARGET_ARCH:=x86 TARGET_ARCH_ABI:=x86 else LOCAL_ARM_MODE := arm endif

LOCAL_MODULE := libffmpegjni LOCAL_SRC_FILES := com_li_sheldon_ffmpeg4android_FFmpegNative.c CarEyeEncoderAPI.cpp FFVideoFilter.cpp CarEyeFilter_interface.cpp LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz LOCAL_SHARED_LIBRARIES:= avcodec-prebuilt-$(LIB_NAME_PLUS) \ avfilter-prebuilt-$(LIB_NAME_PLUS) \ avformat-prebuilt-$(LIB_NAME_PLUS) \ avutil-prebuilt-$(LIB_NAME_PLUS) \ swresample-prebuilt-$(LIB_NAME_PLUS) \ swscale-prebuilt-$(LIB_NAME_PLUS) LOCAL_C_INCLUDES += -L$(SYSROOT)/usr/include LOCAL_C_INCLUDES += $(LOCAL_PATH)/include

ifeq ($(APP_ABI), x86) LOCAL_CFLAGS := -DUSE_X86_CONFIG else LOCAL_CFLAGS := -DUSE_ARM_CONFIG endif include $(BUILD_SHARED_LIBRARY)

编译后生成libffmpegjni.so, 然后提供JNI的源码给上层调用:

[cpp] view plain copy

  1. /* DO NOT EDIT THIS FILE - it is machine generated */  

  2. #include "com_li_sheldon_ffmpeg4android_FFmpegNative.h"  

  3. /* Header for class com_hsb_ffmpeg_FFmpegNative */  

  4. #include "libavcodec/avcodec.h"  

  5. #include "libavcodec/avdct.h"  

  6. #include "libavcodec/avfft.h"  

  7. #include "libavcodec/dirac.h"  

  8. #include "libavcodec/dv_profile.h"  

  9. #include "libavcodec/vaapi.h"  

  10. #include "libavcodec/version.h"  

  11. #include "libavcodec/vorbis_parser.h"  

  12. #include "libavdevice/avdevice.h"  

  13. #include "libavdevice/version.h"  

  14. #include "libavfilter/avfilter.h"  

  15. #include "libavfilter/avfiltergraph.h"  

  16. #include "libavfilter/buffersink.h"  

  17. #include "libavfilter/buffersrc.h"  

  18. #include "libavfilter/version.h"  

  19. #include "libavformat/avformat.h"  

  20. #include "libavformat/avio.h"  

  21. #include "libavformat/version.h"  

  22. #include "libavutil/adler32.h"  

  23. #include "libavutil/aes_ctr.h"  

  24. #include "libavutil/aes.h"  

  25. #include "libavutil/attributes.h"  

  26. #include "libavutil/audio_fifo.h"  

  27. #include "libavutil/avassert.h"  

  28. #include "libavutil/avconfig.h"  

  29. #include "libavutil/avstring.h"  

  30. #include "libavutil/avutil.h"  

  31. #include "libavutil/base64.h"  

  32. #include "libavutil/blowfish.h"  

  33. #include "libavutil/bprint.h"  

  34. #include "libavutil/bswap.h"  

  35. #include "libavutil/buffer.h"  

  36. #include "libavutil/camellia.h"  

  37. #include "libavutil/cast5.h"  

  38. #include "libavutil/channel_layout.h"  

  39. #include "libavutil/common.h"  

  40. #include "libavutil/cpu.h"  

  41. #include "libavutil/crc.h"  

  42. #include "libavutil/des.h"  

  43. #include "libavutil/dict.h"  

  44. #include "libavutil/display.h"  

  45. #include "libavutil/downmix_info.h"  

  46. #include "libavutil/error.h"  

  47. #include "libavutil/eval.h"  

  48. #include "libavutil/ffversion.h"  

  49. #include "libavutil/fifo.h"  

  50. #include "libavutil/file.h"  

  51. #include "libavutil/frame.h"  

  52. #include "libavutil/hash.h"  

  53. #include "libavutil/hmac.h"  

  54. #include "libavutil/imgutils.h"  

  55. #include "libavutil/intfloat.h"  

  56. #include "libavutil/intreadwrite.h"  

  57. #include "libavutil/lfg.h"  

  58. #include "libavutil/log.h"  

  59. #include "libavutil/lzo.h"  

  60. #include "libavutil/macros.h"  

  61. #include "libavutil/mastering_display_metadata.h"  

  62. #include "libavutil/mathematics.h"  

  63. #include "libavutil/md5.h"  

  64. #include "libavutil/mem.h"  

  65. #include "libavutil/motion_vector.h"  

  66. #include "libavutil/murmur3.h"  

  67. #include "libavutil/opt.h"  

  68. #include "libavutil/parseutils.h"  

  69. #include "libavutil/pixdesc.h"  

  70. #include "libavutil/pixelutils.h"  

  71. #include "libavutil/pixfmt.h"  

  72. #include "libavutil/random_seed.h"  

  73. #include "libavutil/rational.h"  

  74. #include "libavutil/rc4.h"  

  75. #include "libavutil/replaygain.h"  

  76. #include "libavutil/ripemd.h"  

  77. #include "libavutil/samplefmt.h"  

  78. #include "libavutil/sha.h"  

  79. #include "libavutil/sha512.h"  

  80. #include "libavutil/stereo3d.h"  

  81. #include "libavutil/tea.h"  

  82. #include "libavutil/threadmessage.h"  

  83. #include "libavutil/time.h"  

  84. #include "libavutil/timecode.h"  

  85. #include "libavutil/timestamp.h"  

  86. #include "libavutil/tree.h"  

  87. #include "libavutil/twofish.h"  

  88. #include "libavutil/version.h"  

  89. #include "libavutil/xtea.h"  

  90. #include "libswresample/swresample.h"  

  91. #include "libswresample/version.h"  

  92. #include "libswscale/swscale.h"  

  93. #include "libswscale/version.h"  

  94. #include "CarEyeEncoderAPI.h"  

  95. #include "CarEyeFilter_interface.h"  

  96. #include <android/log.h>  

  97. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "ffmpeg4android", __VA_ARGS__)  

  98. JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_ffmpeg_1h264  

  99.   (JNIEnv* env, jobject obj, jint codecID)  

  100.  {  

  101.     AVCodec* codec = NULL;  

  102.     av_register_all();//该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等  

  103.     codec = avcodec_find_decoder(codecID);//通过code ID查找一个已经注册的音视频编码器。H264的codecID是28,所以我们java那边传28下来如果检测到H264注册过了这边codec就不为空,返回0  

  104.     if(codec != NULL){  

  105.       return 0;  

  106.     }else{  

  107.       return -1;  

  108.     }  

  109. }  

  110. CarEyeFilter gFliter;  

  111. JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_OpenOSD(JNIEnv* env, jobject obj, jint width, jint height, jint startX, jint startY, jint FontSize,  jint color, jstring  filename, jstring content  )  

  112. {  

  113.     char* Name;  

  114.     char* pContent;  

  115.     gFliter.para.X = startX;  

  116.     gFliter.para.Y = startY;  

  117.     gFliter.para.width = width;  

  118.     gFliter.para.height = height;  

  119.     gFliter.para.FontSize = FontSize;  

  120.     gFliter.para.FontColor = color;  

  121.     gFliter.para.fps = 25;  

  122.     Name=(*env)->GetStringUTFChars(env,filename, JNI_FALSE);  

  123.     pContent=(*env)->GetStringUTFChars(env,content, JNI_FALSE);  

  124.     strcpy(gFliter.para.FontName, Name);  

  125.     strcpy(gFliter.para.SubTitle, pContent);      

  126.     gFliter.para.Transparency = 0.7;       

  127.     (*env)->ReleaseStringUTFChars(env, filename, Name);  

  128.     (*env)->ReleaseStringUTFChars(env, content, pContent);                 

  129.     return CarEye_OpenOsd(&gFliter, gFliter.para);  

  130. }  

  131. JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_CloseOSD(JNIEnv* env, jobject obj)  

  132. {         

  133.     return CarEye_CloseOsd(&gFliter);  

  134. }  

  135. JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_AddOSD(JNIEnv* env, jobject obj, jbyteArray frame, jstring txtoverlay)  

  136. {  

  137.     unsigned char * pBuffer;  

  138.     int ret;  

  139.     char *txt;  

  140.     CarEye_YUVFrame yuv_frame;  

  141.     pBuffer = (*env)->GetByteArrayElements(env,frame, 0 );  

  142.     int len = (*env)->GetArrayLength(env,frame);       

  143.     yuv_frame.Y = pBuffer;  

  144.     yuv_frame.YSize = len*2/3;  

  145.     yuv_frame.U = &pBuffer[len*2/3];  

  146.     yuv_frame.USize = len/6;  

  147.     yuv_frame.V = &pBuffer[len*5/6];  

  148.     yuv_frame.VSize = len/6;  

  149.     txt = (*env)->GetStringUTFChars(env,txtoverlay, JNI_FALSE);  

  150.     strcpy(gFliter.para.SubTitle, txt);      

  151.     ret = CarEye_add_osd(&gFliter,&yuv_frame,gFliter.para);          

  152.    (*env)->ReleaseStringUTFChars(env, txtoverlay, txt);       

  153.    (*env)->ReleaseByteArrayElements(env,frame,pBuffer,0);  

  154.    return ret;  

  155. }

  

OK, 写一个简单例子测试下:

[java] view plain copy

  1. package com.li.sheldon.ffmpeg4android;  

  2. import android.util.Log;  

  3. /** 

  4.  * Created by sheldon on 17-1-4. 

  5.  */  

  6. public class FFmpegNative {  

  7.     static{  

  8.         System.loadLibrary("avcodec-57");  

  9.         System.loadLibrary("avfilter-6");  

  10.         System.loadLibrary("avformat-57");  

  11.         System.loadLibrary("avutil-55");  

  12.         System.loadLibrary("swresample-2");  

  13.         System.loadLibrary("swscale-4");  

  14.         System.loadLibrary("ffmpegjni");  

  15.     }  

  16.     private native int AddOSD(byte[] buffer, String txt);  

  17.     private native int CloseOSD();  

  18.     private native int OpenOSD(int width, int height, int startX, int startY, int fontsize, int color, String  filename, String  content);  

  19.     private native int ffmpeg_h264(int id);  

  20.     public int test_h246(int id){  

  21.         return ffmpeg_h264(id);  

  22.     }  

  23.     public int InitOSD(int width, int height, int startX, int startY, int fontsize, int color, String  filename, String  content)  

  24.     {  

  25.          return OpenOSD(width,height,startX,startY,fontsize,color, filename,content );  

  26.     }  

  27.     public int DelOSD()  

  28.     {  

  29.         return CloseOSD();  

  30.     }  

  31.     public int blendOSD(byte[] buffer,String txt)  

  32.     {  

  33.         return AddOSD(buffer,txt);  

  34.     }  

  35. }

  

[cpp] view plain copy

  1. package com.li.sheldon.ffmpeg4android;  

  2. import android.app.Activity;  

  3. import android.os.Bundle;  

  4. import android.util.Log;  

  5. import android.widget.TextView;  

  6. import java.io.File;  

  7. import java.io.FileInputStream;  

  8. import java.io.FileNotFoundException;  

  9. import java.io.FileOutputStream;  

  10. import java.io.IOException;  

  11. import java.text.SimpleDateFormat;  

  12. import java.util.Date;  

  13. public class MainActivity extends Activity {  

  14.     @Override  

  15.     protected void onCreate(Bundle savedInstanceState) {  

  16.         super.onCreate(savedInstanceState);  

  17.         setContentView(R.layout.activity_main);  

  18.         int codec_id = 28;  

  19.         final FFmpegNative ffmpeg = new FFmpegNative();  

  20.         int tmp = ffmpeg.test_h246(codec_id); //28 is the H264 Codec ID  

  21.         TextView tv = (TextView) this.findViewById(R.id.hello_ffmpeg);  

  22.         tv.setText(tmp == 0 ? "Support Codec ID:" + codec_id : "Not support Codec ID:" + codec_id);  

  23.         Log.d("ffmpeg4android", "OSD init start: ");  

  24.         new Thread(new Runnable() {  

  25.             @Override  

  26.             public void run() {  

  27.                 int loop = 0;  

  28.                 FileOutputStream out;  

  29.                 FileInputStream in;  

  30.                 FFmpegNative ffmpeg = new FFmpegNative();  

  31.                 int ret = ffmpeg.InitOSD(1280, 720, 10, 10, 28, 0x00ff00, String.format("/mnt/sdcard/arial.ttf"), String.format("ddddd"));  

  32.                 if (ret != 0) {  

  33.                     Log.d("ffmpeg4android", "OSD init fail: "+ret);  

  34.                 }  

  35.                 Log.d("ffmpeg4android", "OSD blend ");  

  36.                 byte[] data=new byte[1280*720*3/2];  

  37.                 try {  

  38.                     File f = new File("/mnt/sdcard/out.yuv");  

  39.                     if(f.exists()) f.delete();  

  40.                     f.createNewFile();  

  41.                     out = new FileOutputStream(f);  

  42.                     File input = new File("/mnt/sdcard/input.yuv");  

  43.                     in = new FileInputStream(input);  

  44.                     int len;  

  45.                     while(loop<1000)  

  46.                     {  

  47.                         if(in.read(data,0,1280*720*3/2)<0)  

  48.                         {  

  49.                             Log.d("ffmpeg4android", "read fail:");  

  50.                             break;  

  51.                         }else {  

  52.                             String txt = "car-eye-filter" + new SimpleDateFormat("yyyy-MM-dd").format(new Date())+loop;  

  53.                             int result =  ffmpeg.blendOSD(data, txt);  

  54.                             out.write(data,0,1280*720*3/2);  

  55.                             Log.d("ffmpeg4android", "write data sucessful:"+result+"data[0]"+data[0]);  

  56.                         }  

  57.                         loop++;  

  58.                     }  

  59.                     in.close();  

  60.                     out.close();  

  61.                     ffmpeg.DelOSD();  

  62.                 } catch (Exception e) {  

  63.                     e.printStackTrace();  

  64.                 }  

  65.             }  

  66.         }).start();  

  67.     }  

  68. }

  

 

生成的YUV数据用播放器打开如下

FFMEPG 平台移植,接口简化和外部模块接入 (三)ffmpeg android移植(ffmpeg实现水印文字显示)

car-eye开源官方网址:www.car-eye.cn   

car-eye 流媒体平台网址:www.liveoss.com    

car-eye 技术官方邮箱: support@car-eye.cn    
car-eye技术交流QQ群: 590411159     

FFMEPG 平台移植,接口简化和外部模块接入 (三)ffmpeg android移植(ffmpeg实现水印文字显示)

CopyRight©  car-eye 开源团队 2018

点赞
收藏
评论区
推荐文章
Souleigh ✨ Souleigh ✨
3年前
JS - ES6 的 Module
一、介绍模块,(Module),是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体)。两个基本的特征:外部特征和内部特征外部特征是指模块跟外部环境联系的接口(即其他模块或程序调用该模块的方式,包括有输入输出参数、引用的全局变量)和模块的功能内部特征是指模块的内部环境具有的特点(即该模
可莉 可莉
3年前
041. 通过 Lua 扩展 Nginx
1\.ngx\_lua模块Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。ngx\_lua模块通过将lua解释器集成进Nginx,可以采用lua脚本实现业务逻辑。该模块具有
Wesley13 Wesley13
3年前
Linux 下完整安装ffmpeg(包括各种解码器)
FFmpeg是什么?FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。FFmpeg在Linux平
Stella981 Stella981
3年前
FFMEPG 平台移植,接口简化和外部模块接入 (二)ffmpeg android移植(JNI 开发环境建立)
工欲善其事情,必先利其器。在android下使用ffmpeg必须使用JNI。先创建一个好的编译工具为先:按照下面步骤在androidstdio下创建JNI的编译环境1.配置AnroidStudio(这步是关键)选中项目,单击File菜单,选择Setting进入设置界面。或者按快捷键CtrlAltS。:!(https://img
Wesley13 Wesley13
3年前
Java spi机制浅谈
最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制。所以简单的总结下javaspi机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具
Stella981 Stella981
3年前
FFMEPG 平台移植,接口简化和外部模块接入 (四)ffmpeg android移植(ffmpeg 视频编码)
FFMPEG视频编码最常见的H264,H265需要X264,X265外部模块支持,可以从我们开源平台的FFMPEG编译项目里面获取代码和配置进行一键式编译:https://github.com/Careyeteam/CareyeFFMPEG(https://www.oschina.net/action/GoToLink?urlhttps%3A
Stella981 Stella981
3年前
041. 通过 Lua 扩展 Nginx
1\.ngx\_lua模块Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。ngx\_lua模块通过将lua解释器集成进Nginx,可以采用lua脚本实现业务逻辑。该模块具有
Stella981 Stella981
3年前
FFMEPG 平台移植,接口简化和外部模块接入 (一)ffmpeg android移植(ndk 编译)
CareyeFFMPEG项目是Careye开源平台的一个新项目,目的是在FFMPEG项目和其外部模块,如freetype,X264的基础上建立一个多平台编译,接口调用简单的工具集。本博客是一个连载,首先从android开始写吧。因为FFMPEG本身对android编译的支持就不是特别好。本文开发环境是ubuntu分步来做:1\.建立
Wesley13 Wesley13
3年前
Java中匿名类的两种实现方式
使用匿名内部类课使代码更加简洁、紧凑,模块化程度更高。内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到。然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式:第一种,继承一个类,重写其方法;第二种,实现一个接口(可以是多个),实现其方法。下面通过代码来说明:1.publicclass TestAnonymo
Easter79 Easter79
3年前
TypeScript手册翻译系列4
模块在TypeScript中利用模块(module)来组织代码。这里将讨论内部和外部模块,以及在何时使用哪种方式更合适,以及怎么使用。当然也会讨论一些高级话题,例如如何使用外部模块,以及在TypeScript中使用模块时常见的一些错误。第一步让我们从下面的例子开始,这个例子将会贯穿本文。首先我们写了一段字符串验证代码,用