今天有点时间写WIFICAR了,
前面根据前面几编转载,加上自己的移植,终于完成了小车的所有,并且完成了视平编码成MP4,在编码这里我卡了个把月了,主要是不了解视平的处理,
当我获取到MJPEG数据流,就进行了解码,在进行编码,一直进入了这种错误的思维,正真的编码过程是,MJPEG-> yuvj420-> yuv420-> mp4,,,,MP4的编码数据,
是, I 帧 ,B帧 ,P帧 对这些不了解的可以看博文:IPB帧编码顺序(解码顺序)与显示顺序
要完成视平的编码,就要调用FFMPEG库,(注:这是开源库,要用于商业用途,可能有版权问题)我用的库:ffmpeg0.11
编议在里面的脚本文件,build_ffmpeg.sh,,用的NDK是8 ,没有用H264来编码,所以可以用不X264库
视平解码我参考了:基于嵌入式Linux的视频采集系统-----源程序----decoder.cpp, 这里面就很清楚的说明了怎么得到了YUV数据,最后只要进行编码就行了
void videoCoding(AVFormatContext *oc, AVStream *st){
int out_size, k;
AVCodecContext *c = st->codec;
int size, ret;
LOGE("videoCoding\n");
tmp_picture->pkt_pts = pts++;
out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, tmp_picture);
LOGE("--out_size- %d --\n", out_size);
if(out_size >0)
{
AVPacket pkt;
av_init_packet(&pkt);
if(c->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
if (c->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = st->index;
pkt.data = video_outbuf;
pkt.size = out_size;
ret = av_interleaved_write_frame(oc, &pkt);
}
}
tmp_picture就是转码来的YUV420数据,
参考库中的MUXING.c文件,
这些全是要JNI中完成的,android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg
LOCAL_C_INCLUDES += $(PATH_TO_FFMPEG_SOURCE)
LOCAL_LDLIBS := -lffmpeg1 -llog
LOCAL_MODULE := ffmpegVideoCoding
LOCAL_SRC_FILES := ffmpegVideoCoding.c
include $(BUILD_SHARED_LIBRARY)
JAVA层只要通过进程不停的将得到的数据传下就可以编码成MP4视平了,视频中好像只有 I ,P 帧,所以压缩不是很高,不知道为什么没有B帧的,求高手解答。
public native void videoCondingInitJNI(int width, int height, String fileName);
public native void videoCondingBufferJNI(byte[] in, int insize);
public native void videoCondingEndJNI();
static {
System.loadLibrary("ffmpeg1");
System.loadLibrary("ffmpegVideoCoding");
}
最后,想要客户端源码的,可以到我建的群里下载 96392668 一直没搞过群,里面没什么人,注意:我没有给出JNI C 编码的源码,只有.SO文件