首先来看一副图,用来纪念对视频领域做出贡献的雷神:
当然在这个图片里面的decode不是必须的,Filter 模块本身是一个非常独立的模块,但因为相关的程序,给人造成了他必须要依赖于decoder或者encoder来工作。
OK 不多说,先看看内部实现代码:
[cpp] view plain copy
-
#ifndef __CAREYE_PUBLIC_H__
-
#define __CAREYE_PUBLIC_H__
-
#define __STDC_CONSTANT_MACROS
-
#ifdef _WIN32
-
#define CE_API __declspec(dllexport)
-
#define CE_APICALL __stdcall
-
#else
-
#define CE_API
-
#define CE_APICALL
-
#endif
-
#ifndef _WIN32
-
#define _ANDROID_
-
#endif
-
#ifdef _ANDROID_
-
#include <android/log.h>
-
#define CarEyeLog(...) __android_log_print(ANDROID_LOG_DEBUG, "Car-eye-ffmpeg", __VA_ARGS__)
-
#else
-
#define CarEyeLog printf
-
#endif
-
typedef struct _CarEye_YUVFrame_
-
{
-
// Y分量数据存储区
-
unsigned char *Y;
-
// Y分量数据字节数
-
int YSize;
-
// U分量数据存储区
-
unsigned char *U;
-
// U分量数据字节数
-
int USize;
-
// V分量数据存储区
-
unsigned char *V;
-
// V分量数据字节数
-
int VSize;
-
}CarEye_YUVFrame;
-
//error number
-
#define NO_ERROR 0
-
#define PARAMTER_ERROR 1
-
#define NULL_MEMORY 2
-
#define MAX_FILTER_DESCR 512
-
#endif
[cpp] view plain copy
-
#ifndef __CAREYE_FILTER_INTERFACE_H__
-
#define __CAREYE_FILTER_INTERFACE_H__
-
#define MAX_STRING_LENGTH 1024
-
#define MAX_FILE_NAME 64
-
// OSD水印结果定义
-
typedef struct _CarEye_OSDParam_
-
{
-
int width;
-
int height;
-
int fps;
-
// 起始X轴坐标
-
int X;
-
// 起始Y轴坐标
-
int Y;
-
// 字体大小
-
int FontSize;
-
// 16进制的RGB颜色值,如绿色:0x00FF00
-
unsigned int FontColor;
-
// 水印透明度 0~1
-
float Transparency;
-
// 水印内容
-
char SubTitle[MAX_STRING_LENGTH];
-
// 字体名称,字体文件放到库的同目录下,如“arial.ttf”
-
char FontName[MAX_FILE_NAME];
-
}CarEye_OSDParam;
-
typedef struct
-
{
-
AVFrame *VFrame;
-
// 编码后的音频帧
-
CarEye_OSDParam para;
-
void* handle;
-
}CarEyeFilter;
-
#ifdef __cplusplus
-
extern "C"
-
{
-
#endif
-
/*
-
* Comments: 打开水印资源
-
* Param aEncoder: 编码器对象句柄
-
* Param aParam: 水印参数
-
* @Return int 是否成功,0成功,其他失败
-
*/
-
CE_API int CE_APICALL CarEye_OpenOsd(CarEyeFilter* pFilter, CarEye_OSDParam aParam);
-
/*
-
* Comments: 关闭水印资源
-
* Param aDeocoder: 编码器对象
-
* @Return int 关闭成功与否 0成功
-
*/
-
CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFilter);
-
CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFilter, CarEye_YUVFrame *aYuv, CarEye_OSDParam aParam);
-
#ifdef __cplusplus
-
}
-
#endif
-
#endif
实现部分代码:
[cpp] view plain copy
-
#include "FFVideoFilter.h"
-
/*
-
* Comments: 打开水印资源
-
* Param aEncoder: 编码器对象句柄
-
* Param aParam: 水印参数
-
* @Return int 是否成功,0成功,其他失败
-
*/
-
CE_API int CE_APICALL CarEye_OpenOsd( CarEyeFilter* pFliter, CarEye_OSDParam aParam)
-
{
-
if(pFliter==NULL)
-
{
-
return -PARAMTER_ERROR;
-
}
-
avfilter_register_all();
-
pFliter->VFrame = NULL;
-
pFliter->VFrame = av_frame_alloc();
-
if(pFliter->VFrame == NULL)
-
{
-
return -NULL_MEMORY;
-
}
-
pFliter->VFrame->width = aParam.width;
-
pFliter->VFrame->height = aParam.height;
-
pFliter->VFrame->pts = 0;
-
if (av_image_alloc(pFliter->VFrame->data, pFliter->VFrame->linesize,
-
pFliter->VFrame->width, pFliter->VFrame->height,
-
AV_PIX_FMT_YUV420P, 16) < 0)
-
{
-
CarEyeLog("Cannot av_image_alloc\n");
-
av_frame_free(&pFliter->VFrame);
-
return -NULL_MEMORY;
-
}
-
pFliter->VFrame->format = AV_PIX_FMT_YUV420P;
-
FFVideoFilter *handle = new FFVideoFilter();
-
pFliter->handle =(FFVideoFilter*)handle;
-
return handle->InitFilters( aParam);
-
}
-
CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFliter, CarEye_YUVFrame *aYuv,CarEye_OSDParam param)
-
{
-
if(pFliter==NULL || pFliter->VFrame == NULL)
-
{
-
return -PARAMTER_ERROR;
-
}
-
FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;
-
pFliter->VFrame->pts++;
-
memcpy(pFliter->VFrame->data[0], aYuv->Y, aYuv->YSize);
-
memcpy(pFliter->VFrame->data[1], aYuv->U, aYuv->USize);
-
memcpy(pFliter->VFrame->data[2], aYuv->V, aYuv->VSize);
-
if (handle->BlendFilters(pFliter->VFrame,param) < 0)
-
{
-
return -PARAMTER_ERROR;
-
}
-
memcpy(aYuv->Y, pFliter->VFrame->data[0], aYuv->YSize);
-
memcpy(aYuv->U, pFliter->VFrame->data[1], aYuv->USize);
-
memcpy(aYuv->V, pFliter->VFrame->data[2], aYuv->VSize);
-
return NO_ERROR;
-
}
-
/*
-
* Comments: 关闭水印资源
-
* Param aDeocoder: 编码器对象
-
* @Return int 关闭成功与否 0 成功
-
*/
-
CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFliter)
-
{
-
FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;
-
if(pFliter->VFrame != NULL)
-
{
-
av_frame_free(&pFliter->VFrame);
-
}
-
delete handle;
-
return NO_ERROR;
[cpp] view plain copy
-
#include "FFVideoFilter.h"
-
/*
-
* Comments: 打开水印资源
-
* Param aEncoder: 编码器对象句柄
-
* Param aParam: 水印参数
-
* @Return int 是否成功,0成功,其他失败
-
*/
-
CE_API int CE_APICALL CarEye_OpenOsd( CarEyeFilter* pFliter, CarEye_OSDParam aParam)
-
{
-
if(pFliter==NULL)
-
{
-
return -PARAMTER_ERROR;
-
}
-
avfilter_register_all();
-
pFliter->VFrame = NULL;
-
pFliter->VFrame = av_frame_alloc();
-
if(pFliter->VFrame == NULL)
-
{
-
return -NULL_MEMORY;
-
}
-
pFliter->VFrame->width = aParam.width;
-
pFliter->VFrame->height = aParam.height;
-
pFliter->VFrame->pts = 0;
-
if (av_image_alloc(pFliter->VFrame->data, pFliter->VFrame->linesize,
-
pFliter->VFrame->width, pFliter->VFrame->height,
-
AV_PIX_FMT_YUV420P, 16) < 0)
-
{
-
CarEyeLog("Cannot av_image_alloc\n");
-
av_frame_free(&pFliter->VFrame);
-
return -NULL_MEMORY;
-
}
-
pFliter->VFrame->format = AV_PIX_FMT_YUV420P;
-
FFVideoFilter *handle = new FFVideoFilter();
-
pFliter->handle =(FFVideoFilter*)handle;
-
return handle->InitFilters( aParam);
-
}
-
CE_API int CE_APICALL CarEye_add_osd(CarEyeFilter* pFliter, CarEye_YUVFrame *aYuv,CarEye_OSDParam param)
-
{
-
if(pFliter==NULL || pFliter->VFrame == NULL)
-
{
-
return -PARAMTER_ERROR;
-
}
-
FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;
-
pFliter->VFrame->pts++;
-
memcpy(pFliter->VFrame->data[0], aYuv->Y, aYuv->YSize);
-
memcpy(pFliter->VFrame->data[1], aYuv->U, aYuv->USize);
-
memcpy(pFliter->VFrame->data[2], aYuv->V, aYuv->VSize);
-
if (handle->BlendFilters(pFliter->VFrame,param) < 0)
-
{
-
return -PARAMTER_ERROR;
-
}
-
memcpy(aYuv->Y, pFliter->VFrame->data[0], aYuv->YSize);
-
memcpy(aYuv->U, pFliter->VFrame->data[1], aYuv->USize);
-
memcpy(aYuv->V, pFliter->VFrame->data[2], aYuv->VSize);
-
return NO_ERROR;
-
}
-
/*
-
* Comments: 关闭水印资源
-
* Param aDeocoder: 编码器对象
-
* @Return int 关闭成功与否 0 成功
-
*/
-
CE_API int CE_APICALL CarEye_CloseOsd(CarEyeFilter* pFliter)
-
{
-
FFVideoFilter* handle = (FFVideoFilter*)pFliter->handle;
-
if(pFliter->VFrame != NULL)
-
{
-
av_frame_free(&pFliter->VFrame);
-
}
-
delete handle;
-
return NO_ERROR;
-
}
在写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
-
/* DO NOT EDIT THIS FILE - it is machine generated */
-
#include "com_li_sheldon_ffmpeg4android_FFmpegNative.h"
-
/* Header for class com_hsb_ffmpeg_FFmpegNative */
-
#include "libavcodec/avcodec.h"
-
#include "libavcodec/avdct.h"
-
#include "libavcodec/avfft.h"
-
#include "libavcodec/dirac.h"
-
#include "libavcodec/dv_profile.h"
-
#include "libavcodec/vaapi.h"
-
#include "libavcodec/version.h"
-
#include "libavcodec/vorbis_parser.h"
-
#include "libavdevice/avdevice.h"
-
#include "libavdevice/version.h"
-
#include "libavfilter/avfilter.h"
-
#include "libavfilter/avfiltergraph.h"
-
#include "libavfilter/buffersink.h"
-
#include "libavfilter/buffersrc.h"
-
#include "libavfilter/version.h"
-
#include "libavformat/avformat.h"
-
#include "libavformat/avio.h"
-
#include "libavformat/version.h"
-
#include "libavutil/adler32.h"
-
#include "libavutil/aes_ctr.h"
-
#include "libavutil/aes.h"
-
#include "libavutil/attributes.h"
-
#include "libavutil/audio_fifo.h"
-
#include "libavutil/avassert.h"
-
#include "libavutil/avconfig.h"
-
#include "libavutil/avstring.h"
-
#include "libavutil/avutil.h"
-
#include "libavutil/base64.h"
-
#include "libavutil/blowfish.h"
-
#include "libavutil/bprint.h"
-
#include "libavutil/bswap.h"
-
#include "libavutil/buffer.h"
-
#include "libavutil/camellia.h"
-
#include "libavutil/cast5.h"
-
#include "libavutil/channel_layout.h"
-
#include "libavutil/common.h"
-
#include "libavutil/cpu.h"
-
#include "libavutil/crc.h"
-
#include "libavutil/des.h"
-
#include "libavutil/dict.h"
-
#include "libavutil/display.h"
-
#include "libavutil/downmix_info.h"
-
#include "libavutil/error.h"
-
#include "libavutil/eval.h"
-
#include "libavutil/ffversion.h"
-
#include "libavutil/fifo.h"
-
#include "libavutil/file.h"
-
#include "libavutil/frame.h"
-
#include "libavutil/hash.h"
-
#include "libavutil/hmac.h"
-
#include "libavutil/imgutils.h"
-
#include "libavutil/intfloat.h"
-
#include "libavutil/intreadwrite.h"
-
#include "libavutil/lfg.h"
-
#include "libavutil/log.h"
-
#include "libavutil/lzo.h"
-
#include "libavutil/macros.h"
-
#include "libavutil/mastering_display_metadata.h"
-
#include "libavutil/mathematics.h"
-
#include "libavutil/md5.h"
-
#include "libavutil/mem.h"
-
#include "libavutil/motion_vector.h"
-
#include "libavutil/murmur3.h"
-
#include "libavutil/opt.h"
-
#include "libavutil/parseutils.h"
-
#include "libavutil/pixdesc.h"
-
#include "libavutil/pixelutils.h"
-
#include "libavutil/pixfmt.h"
-
#include "libavutil/random_seed.h"
-
#include "libavutil/rational.h"
-
#include "libavutil/rc4.h"
-
#include "libavutil/replaygain.h"
-
#include "libavutil/ripemd.h"
-
#include "libavutil/samplefmt.h"
-
#include "libavutil/sha.h"
-
#include "libavutil/sha512.h"
-
#include "libavutil/stereo3d.h"
-
#include "libavutil/tea.h"
-
#include "libavutil/threadmessage.h"
-
#include "libavutil/time.h"
-
#include "libavutil/timecode.h"
-
#include "libavutil/timestamp.h"
-
#include "libavutil/tree.h"
-
#include "libavutil/twofish.h"
-
#include "libavutil/version.h"
-
#include "libavutil/xtea.h"
-
#include "libswresample/swresample.h"
-
#include "libswresample/version.h"
-
#include "libswscale/swscale.h"
-
#include "libswscale/version.h"
-
#include "CarEyeEncoderAPI.h"
-
#include "CarEyeFilter_interface.h"
-
#include <android/log.h>
-
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "ffmpeg4android", __VA_ARGS__)
-
JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_ffmpeg_1h264
-
(JNIEnv* env, jobject obj, jint codecID)
-
{
-
AVCodec* codec = NULL;
-
av_register_all();//该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等
-
codec = avcodec_find_decoder(codecID);//通过code ID查找一个已经注册的音视频编码器。H264的codecID是28,所以我们java那边传28下来如果检测到H264注册过了这边codec就不为空,返回0
-
if(codec != NULL){
-
return 0;
-
}else{
-
return -1;
-
}
-
}
-
CarEyeFilter gFliter;
-
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 )
-
{
-
char* Name;
-
char* pContent;
-
gFliter.para.X = startX;
-
gFliter.para.Y = startY;
-
gFliter.para.width = width;
-
gFliter.para.height = height;
-
gFliter.para.FontSize = FontSize;
-
gFliter.para.FontColor = color;
-
gFliter.para.fps = 25;
-
Name=(*env)->GetStringUTFChars(env,filename, JNI_FALSE);
-
pContent=(*env)->GetStringUTFChars(env,content, JNI_FALSE);
-
strcpy(gFliter.para.FontName, Name);
-
strcpy(gFliter.para.SubTitle, pContent);
-
gFliter.para.Transparency = 0.7;
-
(*env)->ReleaseStringUTFChars(env, filename, Name);
-
(*env)->ReleaseStringUTFChars(env, content, pContent);
-
return CarEye_OpenOsd(&gFliter, gFliter.para);
-
}
-
JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_CloseOSD(JNIEnv* env, jobject obj)
-
{
-
return CarEye_CloseOsd(&gFliter);
-
}
-
JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_AddOSD(JNIEnv* env, jobject obj, jbyteArray frame, jstring txtoverlay)
-
{
-
unsigned char * pBuffer;
-
int ret;
-
char *txt;
-
CarEye_YUVFrame yuv_frame;
-
pBuffer = (*env)->GetByteArrayElements(env,frame, 0 );
-
int len = (*env)->GetArrayLength(env,frame);
-
yuv_frame.Y = pBuffer;
-
yuv_frame.YSize = len*2/3;
-
yuv_frame.U = &pBuffer[len*2/3];
-
yuv_frame.USize = len/6;
-
yuv_frame.V = &pBuffer[len*5/6];
-
yuv_frame.VSize = len/6;
-
txt = (*env)->GetStringUTFChars(env,txtoverlay, JNI_FALSE);
-
strcpy(gFliter.para.SubTitle, txt);
-
ret = CarEye_add_osd(&gFliter,&yuv_frame,gFliter.para);
-
(*env)->ReleaseStringUTFChars(env, txtoverlay, txt);
-
(*env)->ReleaseByteArrayElements(env,frame,pBuffer,0);
-
return ret;
-
}
OK, 写一个简单例子测试下:
[java] view plain copy
-
package com.li.sheldon.ffmpeg4android;
-
import android.util.Log;
-
/**
-
* Created by sheldon on 17-1-4.
-
*/
-
public class FFmpegNative {
-
static{
-
System.loadLibrary("avcodec-57");
-
System.loadLibrary("avfilter-6");
-
System.loadLibrary("avformat-57");
-
System.loadLibrary("avutil-55");
-
System.loadLibrary("swresample-2");
-
System.loadLibrary("swscale-4");
-
System.loadLibrary("ffmpegjni");
-
}
-
private native int AddOSD(byte[] buffer, String txt);
-
private native int CloseOSD();
-
private native int OpenOSD(int width, int height, int startX, int startY, int fontsize, int color, String filename, String content);
-
private native int ffmpeg_h264(int id);
-
public int test_h246(int id){
-
return ffmpeg_h264(id);
-
}
-
public int InitOSD(int width, int height, int startX, int startY, int fontsize, int color, String filename, String content)
-
{
-
return OpenOSD(width,height,startX,startY,fontsize,color, filename,content );
-
}
-
public int DelOSD()
-
{
-
return CloseOSD();
-
}
-
public int blendOSD(byte[] buffer,String txt)
-
{
-
return AddOSD(buffer,txt);
-
}
-
}
[cpp] view plain copy
-
package com.li.sheldon.ffmpeg4android;
-
import android.app.Activity;
-
import android.os.Bundle;
-
import android.util.Log;
-
import android.widget.TextView;
-
import java.io.File;
-
import java.io.FileInputStream;
-
import java.io.FileNotFoundException;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
import java.text.SimpleDateFormat;
-
import java.util.Date;
-
public class MainActivity extends Activity {
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
int codec_id = 28;
-
final FFmpegNative ffmpeg = new FFmpegNative();
-
int tmp = ffmpeg.test_h246(codec_id); //28 is the H264 Codec ID
-
TextView tv = (TextView) this.findViewById(R.id.hello_ffmpeg);
-
tv.setText(tmp == 0 ? "Support Codec ID:" + codec_id : "Not support Codec ID:" + codec_id);
-
Log.d("ffmpeg4android", "OSD init start: ");
-
new Thread(new Runnable() {
-
@Override
-
public void run() {
-
int loop = 0;
-
FileOutputStream out;
-
FileInputStream in;
-
FFmpegNative ffmpeg = new FFmpegNative();
-
int ret = ffmpeg.InitOSD(1280, 720, 10, 10, 28, 0x00ff00, String.format("/mnt/sdcard/arial.ttf"), String.format("ddddd"));
-
if (ret != 0) {
-
Log.d("ffmpeg4android", "OSD init fail: "+ret);
-
}
-
Log.d("ffmpeg4android", "OSD blend ");
-
byte[] data=new byte[1280*720*3/2];
-
try {
-
File f = new File("/mnt/sdcard/out.yuv");
-
if(f.exists()) f.delete();
-
f.createNewFile();
-
out = new FileOutputStream(f);
-
File input = new File("/mnt/sdcard/input.yuv");
-
in = new FileInputStream(input);
-
int len;
-
while(loop<1000)
-
{
-
if(in.read(data,0,1280*720*3/2)<0)
-
{
-
Log.d("ffmpeg4android", "read fail:");
-
break;
-
}else {
-
String txt = "car-eye-filter" + new SimpleDateFormat("yyyy-MM-dd").format(new Date())+loop;
-
int result = ffmpeg.blendOSD(data, txt);
-
out.write(data,0,1280*720*3/2);
-
Log.d("ffmpeg4android", "write data sucessful:"+result+"data[0]"+data[0]);
-
}
-
loop++;
-
}
-
in.close();
-
out.close();
-
ffmpeg.DelOSD();
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}).start();
-
}
-
}
生成的YUV数据用播放器打开如下
car-eye开源官方网址:www.car-eye.cn
car-eye 流媒体平台网址:www.liveoss.com
car-eye 技术官方邮箱: support@car-eye.cn
car-eye技术交流QQ群: 590411159
CopyRight© car-eye 开源团队 2018