录像音视频同步原理分析及PTS计算公式

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

录像⾳视频同步原理分析及PTS计算公式
图解分析
⾳视频同步要分别保证开始的PTS⼀样,PTS是控制帧的显⽰时间的,所以要实现⾳视频同步必须分别设置⾳视频的PTS。

注:⾳、视频最后⼀帧的PTS时刻不⼀定相同。

1. 视频时间戳计算
pts = count++ *(1000/fps); //其中count初始值为0,每次打完时间戳count加1.
//在ffmpeg,中的代码为
pkt.pts= count++ * (Ctx->time_base.num * 1000 / Ctx->time_base.den);
2. ⾳频时间戳
pts = count++ * (frame_size * 1000 / sample_rate)
//在ffmpeg中的代码为
pkt.pts= count++ * (Ctx->frame_size * 1000 / Ctx->sample_rate);
FFmpeg例⼦
视频:
// 视频帧的播放时间依赖pts字段,⾳频和视频都有⾃⼰单独的pts
// ⾳视频同步要以视频或⾳频为参考标准,然后控制延时来保证⾳视频的同步,最简单的是以⾳频为准同步视频
// 录⾳编码时pts是⼀定的,由编码器以相同频率写⼊,⾳视频录制时总时长是⼀定的,都在同⼀个时间坐标序列上,但长度不⼀定⼀样 // 计算⾳视频pts,都是根据每秒算出有多少个⾳视频帧,然后根据time_base,算出每帧占有多少个时间单位,即为pts差值
long pts = 0;
// 计算视频公式: pkt.pts = count++ * (Ctx->time_base.num * 1000 / Ctx->time_base.den);
//pts = (codec.Framecnt - 1) * (codec.GetCodecCtx()->pkt_timebase.num * 1000 / codec.GetCodecCtx()->pkt_timebase.den);
pts = (codec.Framecnt - 1) * (codec.GetCodecCtx()->pkt_timebase.num * 1000 / 25);
Console.WriteLine("...........video...pts:" + pts);
// 初始化⾳视频共同的timer
CvNetVideo.Play.AVPtsTimer.Init();
// 调整时间戳与时间轴跑过的timer之间的延时
while (CvNetVideo.Play.AVPtsTimer.Timer<pts)
{
Thread.Sleep(1);
CvNetVideo.Play.AVPtsTimer.Sleep_Count++;
Console.WriteLine("...........video...sleep count:" + CvNetVideo.Play.AVPtsTimer.Sleep_Count);
}
⾳频:
#region 设置⾳频的pts
// 计算⾳频PTS公式:pkt.pts= count++ * (Ctx->frame_size * 1000 / Ctx->sample_rate);
long pts = frame_count++ * (output_codec_context->frame_size * 1000 / output_codec_context->sample_rate);
// 初始化⾳视频共同的timer
CvNetVideo.Play.AVPtsTimer.Init();
// 调整时间戳与时间轴跑过的timer之间的延时
while (CvNetVideo.Play.AVPtsTimer.Timer < pts)
{
Thread.Sleep(1);
CvNetVideo.Play.AVPtsTimer.Sleep_Count++;
Console.WriteLine("...........audio...sleep count:" + CvNetVideo.Play.AVPtsTimer.Sleep_Count);
}
frame->pts = pts;
frame->pkt_dts = pts;
#endregion
Console.WriteLine("...........audio...pts:" + pts);
Timer时间戳计算:
/// <summary>
/// PTS-Timer
/// </summary>
public class AVPtsTimer
{
/// <summary>
/// 初始化时的时间戳
/// </summary>
private static long Start_Stamp { get; set; }
public static bool IsInit = false;
/// <summary>
/// 休眠次数
/// </summary>
public static long Sleep_Count { get; set; }
/// <summary>
/// 时间轴跑过的时间
/// </summary>
public static long Timer { get { return ConvertDataTimeToLong(DateTime.Now) - Start_Stamp; } }
public static void Init()
{
if (IsInit)
{
return ;
}
Start_Stamp = ConvertDataTimeToLong(DateTime.Now);
IsInit = true;
}
/// <summary>
/// 计算时间戳
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static long ConvertDataTimeToLong(DateTime dt)
{
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
TimeSpan toNow = dt.Subtract(dtStart);
long timeStamp = toNow.Ticks;
timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
return timeStamp;
}
}
注:⾳视频同步仍然存在瑕疵,时间戳和延时已处理,但视频还是存在不同步的情况,应该是计算过程中直接使⽤的每秒25帧的值的问题,具体是多少还得再看。

上⽂中的代码是可以执⾏的但是中间的值是有问题的,代码如下:
pts = (codec.Framecnt - 1) * (codec.GetCodecCtx()->pkt_timebase.num * 1000 / codec.GetCodecCtx()->pkt_timebase.den);
int den=codec.GetCodecCtx()->pkt_timebase.den;
den=12800;//导致执⾏的时候pts⼀直为0,所以才改为的25帧每秒(25帧是我代码中视频录制的默认值)。

相关文档
最新文档