解压视频及同步音频流程分析

解压视频及同步音频流程分析

  • 数据 -> 子线程解码原始数据到SafeQueue<AVPacket *>队列中 -> 解码器返回解码到输出数据到SafeQueue<AVFrame *> frame_queue 队列 -> 取切片数据dst_data返回给窗口window -> 比较当前视频时间戳与当前帧音频时间戳 -> 处理视频延时或者追赶处理 -> 达到音视频同步
开始之前先掌握以下几个概念
  • 音视频同步是以音频时间为准,通过减缓视频渲染或者丢帧加快视频渲染的操作来达到同步,但同步不是绝对的,是相对的同步,即相差的时间非常短。
  • 需要两个子线程来处理工作,一个packet线程用来解码,一个frame线程用来同步渲染视频
  • 把AVPacket数据解码需要用到这个方法avcodec_send_packet
1
2
3
4
5
6
7
//avcodec.h
/**
* Supply raw packet data as input to a decoder.
* ...
* /

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
  • 从解码器返回输出到数据给到AVFrame结构体队列中,frame_queue.enQueue(frame);
1
2
3
4
5
6
7

/**
* Return decoded output data from a decoder.
* ...
* /

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
  • sws_scale方法, 获得切片数据dst[], 和slice宽高
1
2
3
4
5
6
7
8
9
10
/**
* Scale the image slice in srcSlice and put the resulting scaled
* slice in the image in dst. A slice is a sequence of consecutive
* rows in an image.
* ...
*/

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
const int srcStride[], int srcSliceY, int srcSliceH,
uint8_t *const dst[], const int dstStride[]);
  • av_q2d方法
1
2
3
4
5
6
7
8
9
10

/**
* Convert an AVRational to a `double`.
* @param a AVRational to convert
* @return `a` in floating-point form
* @see av_d2q()
*/
static inline double av_q2d(AVRational a){
return a.num / (double) a.den;
}

项目链接地址: https://github.com/lgq895767507/QuickPlay