/usr/local/lib/pkgconfig $FFMPEG_ROOT/configure --target-os=linux \ --prefix=$PREFIX \ --disable-encoders \ --disable-decoders \ --disable-muxers \ --disable-demuxers \ --disable-parsers \ --disable-bsfs \ --disable-protocols \ --disable-devices \ --disable-avdevice \ --disable-zlib \ --disable-bzlib \ --enable-cross-compile \ --enable-runtime-cpudetect \ --pkg-config-flags="--static" \ --disable-asm \ --arch=arm \ --enable-armv5te \ --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \ --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \ --disable-stripping \ --nm=$PREBUILT/bin/arm-linux-androideabi-nm \ --sysroot=$PLATFORM \ --enable-nonfree \ --enable-version3 \ --enable-gpl \ --disable-doc \ --disable-ffplay \ --disable-ffserver \ --disable-ffprobe \ --enable-avcodec \ --enable-avformat \ --enable-avutil \ --enable-avfilter \ --enable-avresample \ --enable-swresample \ --enable-swscale \ --enable-postproc \ --enable-libx264 \ --enable-encoder=libx264 \ --enable-decoder=h264 \ --enable-hwaccels \ --enable-memalign-hack \ --disable-debug \ --enable-pthreads \ --disable-filters \ --enable-libfreetype \ --enable-filter=drawbox \ --enable-filter=drawtext \ --enable-avisynth \ --enable-iconv \ --extra-cflags="-Os -s -I$X264_ROOT -I$NDK/sysroot/include -I$PREFIX/include/freetype -I$PREFIX/include/ -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a -mvectorize-with-neon-quad" \ --extra-ldflags="-L$ELIB -L$NDK/sysroot/lib -L$NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a -L$PREFIX/lib" \ --extra-libs="-lfreetype2-static -lstdc++ -lgnustl_static -fexceptions -lsupc++ -llog "
然后添加水印过程中出现水波纹的现象,主要原因是给定的width和height和实际的bitmap不匹配产生。
如下为doubango下编码前添加水印的部分代码:
# include <libavfilter/avfiltergraph.h>
# include <libavfilter/avfilter.h>
# include <libavfilter/avcodec.h>
# include <libavfilter/buffersink.h>
# include <libavfilter/buffersrc.h>
# include <libavutil/avutil.h>
# include <libavutil/imgutils.h>
static AVFilterContext* buffersink_ctx = NULL;
static AVFilterContext* buffersrc_ctx = NULL;
static AVFilterGraph* filter_graph = NULL;
static AVFrame* frame_in = NULL;
static AVFrame* frame_out = NULL;
static int isInited;
static int origin_in_width = 480;
static int origin_in_height = 320;
static char last_wartmark_str[125] = "\0";
static char filters_descr[256] = "\0";
static int init_filters(tmedia_codec_t* self)
{
tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
if (!tmedia_defaults_get_use_water_mark_func_flg()){
return -1;
}
if (tmedia_defaults_get_water_mark_strvalue() == tsk_null){
TSK_DEBUG_ERROR("tmedia_defaults_get_water_mark_strvalue() is null\n");
tmedia_defaults_set_use_water_mark_func_flg(tsk_false, tmedia_defaults_get_water_mark_position_x(), tmedia_defaults_get_water_mark_position_y());
return -1;
}
if (strlen(last_wartmark_str) == 0){
strncpy(last_wartmark_str, tmedia_defaults_get_water_mark_strvalue(), sizeof(last_wartmark_str) - 1);
last_wartmark_str[124] = '\0';
}
if ((tsk_strcmp(last_wartmark_str, tmedia_defaults_get_water_mark_strvalue()) != 0)){
tdav_codec_h264_deinit_filters();
isInited = 0;//refresh filters.
}
strncpy(last_wartmark_str, tmedia_defaults_get_water_mark_strvalue(), sizeof(last_wartmark_str));
//TSK_DEBUG_INFO("init filters ,Picture size: %u ** %u", h264->encoder.context->width, h264->encoder.context->height);
if(!self){
TSK_DEBUG_ERROR("self is null\n");
return -1;
}
int in_width=h264->encoder.context->width;
int in_height=h264->encoder.context->height;
int format = PIX_FMT_YUV420P;
if(!in_width || !in_height) {
TSK_DEBUG_ERROR("in_width\in_height is null\n");
return -1;
}
if( in_width != origin_in_width || in_height != origin_in_height){
tdav_codec_h264_deinit_filters();
isInited = 0;
}
if(isInited){
TSK_DEBUG_INFO("here init graphfilter ok.\n");
return -1;
}
if(filter_graph) {
avfilter_graph_free(&filter_graph);
}
//static char *filters_descr = "drawbox=x=100:y=100:w=50:h=50:color=pink@0.5";
//static char *filters_descr = "drawtext=fontfile=/sdcard/arialbd.ttf:fontsize=30:text=\'6102124695\':x=100:y=x/dar:fontcolor=red@0.5:shadowy=2";
//static char *filters_descr = "drawtext=fontfile=/sdcard/arialbd.ttf:fontsize=30:text=\'6102124695\':x=100:y=x/dar";
//static char *filters_descr = "drawtext=fontsize=30:text=\'6102124695\':fontcolor=red";
char *font_color = "red";
switch(tmedia_defaults_get_water_font_color()){
case 0: //red
font_color = "red";
break;
case 1://green
font_color = "green";
break;
case 2://blue
font_color = "blue";
break;
case 3://black
font_color = "black";
break;
case 4://yello
font_color = "yello";
break;
case 5://oreage
font_color = "oreage";
break;
case 6://white
font_color = "White";
break;
default:
break;
};
if (tmedia_defaults_get_water_font_path() == tsk_null){
snprintf(filters_descr, sizeof(filters_descr), "drawtext=fontfile=/sdcard/arialbd.ttf:fontsize=%d:text=%s:x=%d:y=%d:fontcolor=%s@0.6:borderw=2:bordercolor=black@0.6",
tmedia_defaults_get_water_font_size(),
tmedia_defaults_get_water_mark_strvalue(),
tmedia_defaults_get_water_mark_position_x(),
tmedia_defaults_get_water_mark_position_y(),
font_color);
}else{
snprintf(filters_descr, sizeof(filters_descr), "drawtext=fontfile=%s:fontsize=%d:text=%s:x=%d:y=%d:fontcolor=%s@0.6:borderw=2:bordercolor=black@0.6",
tmedia_defaults_get_water_font_path(),
tmedia_defaults_get_water_font_size(),
tmedia_defaults_get_water_mark_strvalue(),
tmedia_defaults_get_water_mark_position_x(),
tmedia_defaults_get_water_mark_position_y(),
font_color);
}
avfilter_register_all();
char args[512];
int ret = 0;
AVFilter *buffersrc = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("buffersink");
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
filter_graph = avfilter_graph_alloc();
if (!outputs || !inputs || !filter_graph) {
ret = AVERROR(ENOMEM);
goto end;
}
/* buffer video source: the decoded frames from the decoder will be inserted here. */
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
in_width, in_height, PIX_FMT_YUV420P,
1, tmedia_defaults_get_video_fps(),
1, 1);
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
args, NULL, filter_graph);
if (ret < 0) {
TSK_DEBUG_ERROR("Cannot create buffer source, %d, \n", ret);
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
goto end;
}
/* buffer video sink: to terminate the filter chain. */
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
NULL, NULL, filter_graph);
if (ret < 0) {
TSK_DEBUG_ERROR("Cannot create buffer sink, %d, \n", ret);
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
goto end;
}
ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
TSK_DEBUG_ERROR("Cannot set output pixel format, %d, \n", ret);
av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
goto end;
}
/*
* Set the endpoints for the filter graph. The filter_graph will
* be linked to the graph described by filters_descr.
*/
/*
* The buffer source output must be connected to the input pad of
* the first filter described by filters_descr; since the first
* filter input label is not specified, it is set to "in" by
* default.
*/
outputs->name = av_strdup("in");
outputs->filter_ctx = buffersrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
/*
* The buffer sink input must be connected to the output pad of
* the last filter described by filters_descr; since the last
* filter output label is not specified, it is set to "out" by
* default.
*/
inputs->name = av_strdup("out");
inputs->filter_ctx = buffersink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr,
&inputs, &outputs, NULL)) < 0){
TSK_DEBUG_ERROR("avfilter_graph_parse_ptr failed, ret:%d.\n", ret);
goto end;
}
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0){
TSK_DEBUG_ERROR("avfilter_graph_config failed, ret:%d.\n", ret);
goto end;
}
if (ret == 0){
frame_in = av_frame_alloc();
unsigned char* frame_buffer_in = (unsigned char*)av_malloc(av_image_get_buffer_size(format,in_width, in_height, 1));
av_image_fill_arrays(frame_in->data, frame_in->linesize, frame_buffer_in, format,in_width, in_height, 1);
frame_out = av_frame_alloc();
/* unsigned char* frame_buffer_out = (unsigned char*)av_malloc(av_image_get_buffer_size(format,in_width, in_height, 1));
av_image_fill_arrays(frame_out->data, frame_out->linesize, frame_buffer_out,format,in_width, in_height, 1);
*/
}
TSK_DEBUG_INFO("init graphfilter ok.\n");
isInited = 1;
end:
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);
return ret;
}
//
static int tdav_codec_h264_deinit_filters(){
if (!isInited){
return;
}
isInited = 0;
if (frame_in != NULL){
av_frame_free(&frame_in);
}
if (frame_out != NULL){
av_frame_free(&frame_out);
}
if (buffersink_ctx != NULL){
avfilter_free(buffersink_ctx);
buffersink_ctx = NULL;
}
if (buffersrc_ctx != NULL){
avfilter_free(buffersrc_ctx);
buffersrc_ctx = NULL;
}
if (filter_graph != NULL){
//avfilter_graph_free(&filter_graph);
}
last_wartmark_str[0] = '\0';
}
//
static int tdav_codec_h264_add_water_marker(tmedia_codec_t* self, AVFrame* frame_src, const unsigned char* in_data){
//TSK_DEBUG_ERROR("enter tdav_codec_h264_add_water_marker\n");
if (!tmedia_defaults_get_use_water_mark_func_flg()){
return -1;
}
if(!isInited) {
TSK_DEBUG_INFO(" graphfilter not inited.\n");
return -1;
}
int ret;
//AVFrame* frame_out = NULL;
tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
//TSK_DEBUG_INFO("Picture size: %u ** %u", h264->encoder.context->width, h264->encoder.context->height);
if(!self){
TSK_DEBUG_ERROR("self is null\n");
return -1;
}
int in_width=h264->encoder.context->width;
int in_height=h264->encoder.context->height;
int format = PIX_FMT_YUV420P;
if(!in_width || !in_height) {
TSK_DEBUG_ERROR("in_width\in_height is null\n");
return -1;
}
//init frame out
//frame_out = av_frame_alloc();
/*
unsigned char* frame_buffer_out = (unsigned char*)av_malloc(av_image_get_buffer_size(format,in_width, in_height, 1));
av_image_fill_arrays(frame_out->data, frame_out->linesize, frame_buffer_out,format,in_width, in_height, 1);
*/
if (!frame_in || !frame_out) {
TSK_DEBUG_ERROR("Could not allocate frame\n");
return -1;
}
frame_in->width=in_width;
frame_in->height=in_height;
frame_in->format=format;
// TSK_DEBUG_ERROR("frame_in width is %d, height is %d \n",frame_in->width, frame_in->height );
//copy data
//0. copy data to frame_in
memcpy(frame_in->data[0], frame_src->data[0], in_width*in_height);
memcpy(frame_in->data[1], frame_src->data[1], in_width*in_height*1/4);
memcpy(frame_in->data[2], frame_src->data[2], in_width*in_height*1/4);
// 1.add frame to filtergraph
// ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame_in, 0);
ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame_in, AV_BUFFERSRC_FLAG_KEEP_REF);
if(ret < 0) {
TSK_DEBUG_ERROR("Cannot add frame to graph \n");
TSK_DEBUG_ERROR("Cannot add frame to graph,ret is %d \n",ret);
goto end;
}
// 2.pull filtered pictures from the filtergraph
ret = av_buffersink_get_frame(buffersink_ctx, frame_out);
if(ret < 0) {
TSK_DEBUG_ERROR("Cannot get frame from graph \n");
TSK_DEBUG_ERROR("Cannot get frame from graph,ret is %d \n",ret);
goto end;
}
//3. copy data to frame_src
//ret = av_frame_copy(frame_src, frame_out);
//memcpy(frame_src->data[0], frame_out->data[0], in_width*in_height);
//memcpy(frame_src->data[1], frame_out->data[1], in_width*in_height*1/4);
//memcpy(frame_src->data[2], frame_out->data[2], in_width*in_height*1/4);
av_image_copy(frame_src->data, frame_src->linesize, frame_out->data, frame_out->linesize, PIX_FMT_YUV420P, in_width, in_height);
end:
//av_frame_free(&frame_out);
av_frame_unref(frame_out);
return ret;
}
//编码前先将bitmap的yuv数据添加水印
#if ADD_WATER_MARKER
//tdav_codec_h264_init_filters(self);
init_filters(self);
tdav_codec_h264_add_water_marker(self, h264->encoder.picture, (const unsigned char*)in_data);
//tdav_codec_h264_add_water_marker2((const unsigned char*)in_data, in_size);
#endifffmpeg编码参数优化:
if((ret = av_opt_set_double(self->encoder.context->priv_data, "crf", (double)30, 0))){
TSK_DEBUG_ERROR("Failed to set x264 crf 28.0");
return;
}
//ultrafast veryfast superfast
if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "superfast", 0))){
TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
}encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;//H264_RTP_PAYLOAD_SIZE大小为1300if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))){ TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);}
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com
