ffmpeg音视频同步

在调用ffmpeg函数合并音视频流时,最让人摸不着头脑的是音视频的时间戳同步问题,稍不注意就会导致服务端解析出错,播放不出画面来。
先解释一下ffmpeg里的timebase,这个就是ffmpeg里计量的时间单位。
一般视频encoder的timebase是1/fps,音频encoder的timebase是1/samplerate。
stream的timebase都是1/1000,表示ms
在编码时,送入编码器的frame会置pts,视频frame的pts是当前的帧数、duration是1,音频frame的pts是当前总共发送的sample数、duration是一帧的sample数(aac是1024)
编码器中如果编码器类型不是AV_CODEC_CAP_DELAY时,会将frame的pts赋值给pkt的pts
应用层在获取到pkt时,直接用里面的pts即可。
但是h264和aac偏偏都是AV_CODEC_CAP_DELAY类型,pkt的pts需要应用层来赋值。可以用下面的函数

pkt.pts=av_rescale_q(frame.pts, out_codec_ctx->time_base, out_stream->time_base);
pkt.duration=av_rescale_q(frame.duration, out_codec_ctx->time_base, out_stream->time_base);

av_rescale_q函数的作用是将codec的时间单位换算成发送流stream的时间单位,公式为

(frame.pts*out_codec_ctx->time_base)/out_stream->time_base

代入计算后,视频pkt的duration就是1*1000/25=40ms,aac音频pkt的duration是1024*1000/16000=64ms(取samplerate为16k)

还有一点要注意的是,在推送h264和aac的rtmp流时,需要将codec的extradata赋值给stream,代码如下

out_stream->codecpar->extradata_size = out_codec_ctx->extradata_size;
out_stream->codecpar->extradata = static_cast(av_mallocz(out_codec_ctx->extradata_size));
memcpy(out_stream->codecpar->extradata, out_codec_ctx->extradata, out_codec_ctx->extradata_size);

这样在avformat_write_header时才会将h264和aac相关编码信息发送到服务端。
具体代码可以参考 https://github.com/lipku/python_rtmpstream

你可能感兴趣的:(音视频传输,ffmpeg,音视频)