音视频开发系列
Android音视频开发 -> ffmpeg+h264+aac编译以及测试调用
Android音视频开发 -> ffmpeg+h264+avfilter+camera推流旋转角度
Android音视频开发 -> fdk-aac编码pcm为eld-aac
Android音视频开发 -> fdk-aac解码eld-aac为pcm
大体思路
- ffmpeg推流相关组件初始化
- avFilter初始化
- 264编码器初始化
- 接收摄像头的实时数据开始推流,这个数据格式需要转换摄像头是NV21的需要转换成YUV420P
公共变量
//解封装全局上下文
AVFormatContext *avFormatContext;
//流通道,存储音视频流
AVStream *video_st;
//解码信息上下文
AVCodecContext *pCodecCtx;
//解码器返回指针对象
AVCodec *pCodec;
//解码前数据结构体
AVPacket enc_pkt;
//储存原始数据流
AVFrame *pFrameYUV;
int count = 0;
//初始化分辨率
int width;
int height;
//初始化YUV分辨率
int yuv_width;
int yuv_height;
//计算Y长度
int y_length;
//计算UV长度
int uv_length;
//帧率(表示一秒上传多少张图片人眼一般感觉流畅是24帧)
int fps = 24;
//水印标识
int flags = 0;
//AVFilter相关
const char *filters_descr;
AVFilterContext *buffersink_ctx = NULL;
AVFilterContext *buffersrc_ctx = NULL;
AVFilterGraph *filter_graph;
//推流地址
const char *out_path;
//是否第一次初始化编码器
int initFlag = 0;
ffmpeg推流以及avFilter初始化
int PushFLow::pushInit(JNIEnv *env, jstring pushPath, int mWight, int mHight, int flag) {
//释放资源
close();
initFlag = 0;
//初始化分辨率
width = mWight;
height = mHight;
//计算yuv数据的长度
yuv_width = width;
yuv_height = height;
y_length = width * height;
uv_length = width * height / 4;
//获取用户输入flag
flags = flag;
//获取推流地址
out_path = env->GetStringUTFChars(pushPath, 0);
//注册组件
av_register_all();
//初始化网络库
avformat_network_init();
//创建输出上下文
avformat_alloc_output_context2(&avFormatContext, NULL, "flv", out_path);
//初始化AVFrame
pFrameYUV = av_frame_alloc();
//AVFilter相关
if (flags != 0) {
if (flags == 1) filters_descr = "transpose=1";
if (flags == 2) filters_descr = "movie=/sdcard/test.png[wm];[in][wm]overlay=1:5[out]";
if (flags == 3)
filters_descr = "drawtext=fontsize=56:fontcolor=green:text='Hello World'";
if (avFilterInit(filters_descr) < 0) {
LOGE("初始化AVFilter失败");
close();
return -1;
}
}
return 0;
}
int PushFLow::avFilterInit(const char *filters_descr) {
char args[512];
//分配AVFilterGraph
filter_graph = avfilter_graph_alloc();
//设置参数(未知)
enum