音视频同步-ffmpeg

        音视频同步肯定是需要使用时间戳进行同步的,音频和视频的时间戳进行对比,哪个小就写入哪个包,基本上可以实现音视频同步。

但是这个时间戳从哪里来呢?

        使用rtp头中携带的时间戳是最正确的方法,因为音视频流发出的时候,将时间戳写入到了rtp头中。不管网络是否有阻塞、丢帧等问题,使用此时间戳进行同步,最终生成的视频文件中音频和视频都是同步的,且视频长度也正常。在此记录一下

        使用ffmpeg直接接收rtp视频和音频媒体流,再将rtp包中的时间戳转换一下,即可实现音视频同步;

      从av_read_frame中 收到的视频帧,带的时间戳需要根据输出流的时间基准进行转换,每个包要显示的时长duration都是0,需要自己进行计算。计算法如下

if(av_read_frame(ifmt_ctx_v, &pkt) >=0)
{
    if (pkt.duration == 0 && ((pkt.pts - last_pts_v)>0))
	{
		pkt.duration = av_rescale_q((pkt.pts - last_pts_v), in_stream->time_base, ofmt_ctx->streams[stream_index]->time_base);
	}
	    last_pts_v = pkt.pts;
		pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, ofmt_ctx->streams[stream_index]->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
		pkt.dts = pkt.pts;					
		pkt.pos = -1;
		printf("timebase convert after pkt.pts =%d\n",pkt.pts);
		printf("timebase convert after pkt.dts =%d\n",pkt.dts);
		printf("timebase convert after pkt.duration =%d\n",pkt.duration);
		printf("frame_index =%d\n",frame_index);
		if (frame_index == 0)
		{
		    frame_index++;
			p_pkt_last = av_packet_clone(&pkt);
			av_packet_unref(&pkt);
						
			printf("frame_index == 0 convert p_pkt_last->pts =%d\n",p_pkt_last->pts);
			printf("frame_index == 0 convert p_pkt_last->dts =%d\n",p_pkt_last->dts);
			printf("frame_index == 0 convert p_pkt_last->duration =%d\n",p_pkt_last->duration);
			continue;
		}
		else
		{
			frame_index++;
						
			p_pkt_last->duration = pkt.duration;
					
			printf("convert p_pkt_last->pts =%d\n",p_pkt_last->pts);
			printf("convert p_pkt_last->dts =%d\n",p_pkt_last->dts);
			printf("convert p_pkt_last->duration =%d\n",p_pkt_last->duration);
			nxt_pts_v = p_pkt_last->pts;
			ret = av_interleaved_write_frame(ofmt_ctx, p_pkt_last);
												
			av_packet_unref(p_pkt_last);
			p_pkt_last = NULL;
			p_pkt_last = av_packet_clone(&pkt);
			av_packet_unref(&pkt);
						
			continue;
		}
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值