您的位置:首页 > 移动开发 > Android开发

直播推流技术及android jni回调java方法总结

2016-06-30 22:54 399 查看
》 业内直播推流用2种技术,ffmpeg  推流flv  aac;  librtmp 用adobe公司的非开源库进行推流;

》推流注意问题,音视频同步,推流规格一般是700bps,15fps,vga,audio  44k 16bit stereo 96kps, gop 2s以内;

》音视频同步的基本原理是rtp传输包时间戳一样,即gettimeofday转换成us,--》27mhz(或者其它多少)时钟来处理;

    ffmpeg会把pts底层转换成rtp的相应时间戳;最简单的做法是v为基准;a相对v值,按绝对包数,时刻保持一定的累增即可。详细见推流代码;

》android jni回调java;网上有一个demo靠谱:  http://my.oschina.net/ffay/blog/313225;

   其中 (*evn)->CallVoidMethod(evn, mobj, mid, jstr);可以在多线程里面自由调用;

》视频推流要保证频率和帧率保持一致;否则服务器会带来累积延时和音视频不同步;音视频不同步带来的现象也差不多。

》ffmpeg增加三方库,链接成一个so的方法,configure按标准的配置,并制定extern include /lib,打开lib编解码支持;链接的时候,-i所有代码的.o包括三方库;最后-output ffmpeg.so即可生成;  编码的时候貌似ffmpeg aac会和faac共用一个codec id;默认会用mac的;可以将aac disable掉, faac enable;

》android音频采集可以用jni层的采集接口,刚好是20ms一帧,aac编码要凑够4096字节buf;故需要做判断。每一帧上述音频规格的话,系统接口获取的数据是3528 bytes

》ffmpeg 调用avformat_open_input会产生超时阻塞1.5分钟左右;解决方法可以设置callback;callback 返回0,就会释放阻塞,报错;返回1就正常等待。本人打开rtsp发现diction用"timeout"  、 "rtsp_transport " "tcp"也进不了回调;只有用这个才能进入回调,“rtsp_transport ”   “udp”; 因为rtsp的包是udp的。类似code如下:

pFormatCtx = avformat_alloc_context();

pFormatCtx->interrupt_callback.callback = interrupt_cb;--------注册回调函数

pFormatCtx->interrupt_callback.opaque = pFormatCtx;

AVDictionary* options = NULL;

av_dict_set(&options, "rtsp_transport", "udp", 0);

// ret = avformat_open_input(&pFormatCtx, cFullPath, 0, &options);

//avformat_network_init();

// Open video file

if(avformat_open_input(&pFormatCtx, [url cStringUsingEncoding:NSASCIIStringEncoding], 0, &options) != 0) {

av_log(NULL, AV_LOG_ERROR, "Couldn't open file\n");

goto initError;

}

static int interrupt_cb(void *ctx)
{
// do something
NSLog(@"%d",time_out);
time_out++;
if (time_out > 40) {
NSLog(@"------%d", firsttimeplay);
time_out=0;
if (firsttimeplay) {
firsttimeplay=0;
NSLog(@"++++++++");
return 1;//这个就是超时的返回
}
}
return 0;
}


》ffmpeg api调用注意: av_init_packet(avpacket) 参考头文件说明,它只能初始化结构体的option member,不能对 data  ,size成员进行初始化。故需要手动初始化,建议空包需要所有初始化的地方替换如下,否则容易导致后续各种因为size不对的问题的隐含错误。
memset(&pkt, 0 ,siezof(avpacket)); av_init_packet( &pkt );  
》ffmpeg avformat_seek_file底层调用的是av_seek_frame(x,x,x,flags);其中flags有1,2,4,8三种方式,其中8 AVSEEK_FLAG_FRAME基于关键帧进行跳转,发现精度是最高的。

》ffmpeg avformat_seek_file底层调用的是av_seek_frame(x,x,x,flags);其中flags有1,2,4,8三种方式,其中8 AVSEEK_FLAG_FRAME基于关键帧进行跳转,发现精度是最高的。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: