》 业内直播推流用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靠谱: ;
其中 (*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基于关键帧进行跳转,发现精度是最高的。