zoukankan      html  css  js  c++  java
  • ffmpeg 播放器原理

    1  播放器过程

    线程1 : readPackets-------》 audio_packets队列   video packets 队列

    线程2: decodeAudio && play

    线程3: decodeVideo---》扔到videoFrames队列里, 如果AVFrame乱序则需要排序

    线程4: playVideo, 视频时钟和音频时钟比较得到delay ----》 Sleep(delay)-----》play  



    2. 同步过程(很重要)
    时钟 Audio :
    
    get_audio_clock(){
      pts = audio_clock  -    (double)hw_buf_size / bytes_per_sec (没有播放的数据时间) ; 
      return pts; 
    }
    
    pts = (double)pFrame->reordered_opaque  *  av_q2d(is->pFormatCtx->streams[is->VideoStream]->time_base)  // 单位秒;
    
    //更新视频内部时钟  以视频时钟为基准同步才有用
     //is->video_clock = pts + av_q2d(is->pVideoCodecCtx->time_base) ;  //如果是30帧率, 那么time_base 就等于   0.0333;
    
     delay = pts - is->frame_last_pts;  //算出大致的延迟时间
    
    diff = pts - get_audio_colock();
    
    delay =   diff<-thresh ? 0 diff>thresh ? 1.6*delay : delay  //diff太小了  delay就小一点,diff 太大了  delay就大一点
    actual_delay = delay + is->frame_timer - av_gettime()/1000000 //算出实际延时 实际延时就等于上一次的 delay -(getTimeLast - getTimeCurr)(程序运行耗时)
    Sleep((int)(actual_delay * 1000 + 0.5));

     3. 音频解码+播放

    fill_audio(void *udata,Uint8 *stream,int len){
    
      player->m_AudioPackQueue.packet_queue_get(player->m_TempPack,1); //从队列拿包
      len1 = avcodec_decode_audio3;//解码
      audio_clock = AVPacket ::pts   *  av_q2d(AVStream::time_base);//音频时钟
      memcpy(stream...);//喂给播放器
    
    }

    2. 一些变量的含义 

    2.1 timebase

      pFormatCtx->streams[0]->time_base:   1/90000。为什么是90000?因为mpeg的pts、dts都是以90kHz来采样的,所以采样间隔为1/90000秒。

      AVPacket下的pts和dts以AVStream->time_base为单位(数值比较大)。这也很容易理解,根据mpeg的协议,压缩后或解压前的数据,pts和dts是90kHz时钟的采样值,时间间隔就是AVStream->time_base。

    AVFrame里面的pkt_pts和pkt_dts是拷贝自AVPacket,同样以AVStream->time_base为单位;而pts是为输出(显示)准备的,以AVCodecContex->time_base为单位)。//FIXME

      codec/decode层timebase,h264随着帧率变化例如1:25 aac根据采样率变化例如1:44100。

    从上面可以看到,InputStream下的pts和dts以AV_TIME_BASE为单位(微秒),至于为什么要转化为微妙,可能是为了避免使用浮点数。

    综上: streams  AVPacket     AVFrame  都是同样的timebase=1/90K           codec/decode    timebase=1/25 (随帧率变化)   

     

    如果要获得当前时钟(秒)   seconds =   av_q2d(timeBase) * pts;

     

  • 相关阅读:
    kettle安装及初步使用
    Datax初步使用
    可修改性及其实现战术(hot words)
    淘宝网的六个质量属性
    python数据可视化笔记---——matplotlib.pyplot()
    Linux虚拟环境virtualevn
    deepin安装虚拟环境virtualenv
    python面试题-web后端
    rabbitmq和redis用作消息队列的区别
    nginx配置项概括说明
  • 原文地址:https://www.cnblogs.com/luoyinjie/p/11563713.html
Copyright © 2011-2022 走看看