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