各位兄弟,请问如何利用Ffmpeg进行音视频同步,非常感谢!(有代码)

ljinchi 2009-05-14 10:47:09
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx;
int i, videoStream;
int audioStream;
AVPacket packet;

FILE *hVideo;
FILE *hAudio;

const char *input_file_name = "F:\\FFmpeg-full-SDK-3.2\\res\\src\\2.ts";// 2.ts为采用h264和mp3编码的文件
const char *output_file_name = "F:\\FFmpeg-full-SDK-3.2\\res\\dst\\2.h264";
const char *output_file_name2 = "F:\\FFmpeg-full-SDK-3.2\\res\\dst\\2.mp3";

hVideo = fopen(output_file_name, "wb+");
if(hVideo == NULL)
{
return 0;
}

hAudio = fopen(output_file_name2, "wb+");
if(hAudio == NULL)
{
return 0;
}

// Register all formats and codecs
av_register_all();

// Open video file
if(av_open_input_file(&pFormatCtx, input_file_name, NULL, 0, NULL)!=0)
return -1;

// Retrieve stream information
if(av_find_stream_info(pFormatCtx) < 0)
return -1;

// Dump information about file onto standard error
dump_format(pFormatCtx, 0, input_file_name, false);

// Find the first video stream
videoStream = -1;
audioStream = -1;
for(i = 0; i < pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
{
videoStream = i;
}
else if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
{
audioStream = i;
}
}
if(videoStream == -1)
{
return -1;
}

while(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index == videoStream)
{
int len;
len = fwrite(packet.data, 1, packet.size, hVideo);
//fwrite(&packet.pts, 1, sizeof(int64_t), hVideo);
}
else if(packet.stream_index == audioStream)
{
fwrite(packet.data, 1, packet.size, hAudio);
//fwrite(&packet.pts, 1, sizeof(int64_t), hAudio);
}

// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}

av_close_input_file(pFormatCtx);

fclose(hVideo);
fclose(hAudio);

return 0;
}


如上代码可以分离出视频和音频,但有个问题,我想把2.h264和2.mp3分别放到不同的线程进行播放(解码)。要如何才能保证2.h264文件和2.mp3文件同步播放呢。非常感谢!
...全文
4333 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianyouairen 2010-06-18
  • 打赏
  • 举报
回复
mark
findhzjob 2010-03-24
  • 打赏
  • 举报
回复
3GP/MP4视频转换大师是一款功能强大的手机3GP、MP4播放器、FLV、WMV、ASF视频转换工具,它可以帮助您将几乎所有流行的视频格式,如:RM、RMVB、AVI、VOB、DAT、VCD、SVCD、ASF、MOV、QT、MPEG、WMV、 MP4、3GP、DivX、XviD、IAVI、SWF、FLV等视频换为FLV,WMV,ASF,手机3GP或MP4播放器(IPOD, PSP等)所支持的视频格式,也可以抽取其中的视频为MP3,WMA音频格式
一:它是一款绿色软件,免安装
二:简单易用,转换效率高
三:支持批量转换
四:支持裁剪视频片段,选择您所需要的视频。
五:支持更改音视频参数,更改视频大小,帧率等,让用户观看视频更舒适

http://www.newhua.com/soft/100690.htm

出售此软件源代码,需要联系QQ 442357047



HHunter 2009-07-29
  • 打赏
  • 举报
回复
关注,学习学习...
希望高人能来解决....
ljinchi 2009-06-06
  • 打赏
  • 举报
回复
由于时间比较急,没办法再去仔细研究音视频同步了,公司领导一直在催这个问题,如果哪位兄弟能具体说一下关于如何控制音视频同步问题,我自己来实现它,给予适当的报酬,表达一下心意也是可以的。谢谢。
我的邮箱:ljinchi@163.com
QQ:24385971
ljinchi 2009-06-06
  • 打赏
  • 举报
回复
谢谢各位的建议。
我把上面的while循环部分改成如下
while(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index == videoStream)
{
len = fwrite(&packet.pts , 1, 8, hVideo);
len = fwrite(&packet.size , 1, 4, hVideo);
len = fwrite(packet.data, 1, packet.size, hVideo);
}
else if(packet.stream_index == audioStream)
{
len = fwrite(&packet.pts, 1, 8, hAudio);
len = fwrite(&packet.size , 1, 4, hAudio);
len = fwrite(packet.data, 1, packet.size, hAudio);
}

// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
在代码中,当执行av_read_frame(pFormatCtx, &packet)后,我直接把packet中的pts保存到音频或视频文件中。但从packet获取到的pts值如下:
视频pts值0 3600 7200 10800 ...//按3600递增
音频pts值0 2351 4702 7053 ...//按2351递增

接下来,我把上面转出来的2.h264和2.mp3文件放在pc端,然后在pc端,用两个线程分别进行发送到下位机。PC端根据上面的pts值控制发送速度,采用以音频为主进行同步,当视频时间戳大于音频时间戳,则丢弃视频帧。而在下位机则用两个线程分别接收音频和视频,然后分别对音频和视频进行解码。但现在出现的问题是音视频能正常播放,但不能同步!我现在对获取到的音视频pts值特别不理解。没有达到控制音视频播放速度的效果,获取到的音频pts和视频pts怎么差别那么大?获取到的音视频pts能否直接比较?

附:
1.看了http://www.dranger.com/ffmpeg/tutorial05.html后,它是采用ffmpeg+SDL,看了晕乎乎。以前都没有接触过这方面的东西。

2.“ jinlking 兄弟的建议 pts *= av_q2d(is->video_st->time_base); 还要与一个基本的时间单位相乘”

这边av_q2d(is->video_st->time_base)后的值,
应该就是pFormatCtx->streams[videoStream]->time_base.num / pFormatCtx->streams[videoStream]->time_base.den吧?这样算出来的话,音视频都是1/90000吧 ?音视频都乘以这个time_base,跟没有乘以time_base效果是一样的,还是我的理解错了?
3.ffplay.c中的音视频同步代码,哪位兄弟能详细分析一下。

关于音视频同步问题,比较急,希望大家能帮帮我,再次谢谢大家。
pund121 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 lius1984 的回复:]
ffmpeg为了支持最多格式 只是用av_read_frame实现了个音视频同步的框架而已,但完全照他的方式 效果肯定不好 。 另外你为什么要dump出音视频文件再同步? 可以搞个缓冲区试试。 当然这是流媒体播放器的思路了 呵呵
[/Quote]

创建 缓冲区,视音频的写入读取的问题?
tellmey 2009-06-03
  • 打赏
  • 举报
回复
mark
iris2000 2009-06-02
  • 打赏
  • 举报
回复
我进来学习一下。
楼主在TS demux出来存成Video和Audio两个文件的时候,是不是应该把时间戳的信息也保存出来啊,不然的话单独只有一个audio和一个video的数据文件,同步从何谈起啊?
油菜好菜 2009-05-31
  • 打赏
  • 举报
回复
一般有三种办法
1.以音频为主进行同步
2.以视频为主进行同步
3.以一个外部参考时钟为同步
你可以参考下ffmpeg下的ffplay来做,还有
http://www.dranger.com/ffmpeg/tutorial05.html 和
http://www.dranger.com/ffmpeg/tutorial04.html
具体如何实现还是要靠自己研究清楚代码后来解决的.
sofar1000 2009-05-20
  • 打赏
  • 举报
回复
网上有教程,http://www.dranger.com/ffmpeg/tutorial05.html
这个教程是用ffmpeg+SDL来实现视音频的插放与同步,同步还是要用到AVPacket的PTS和DTS、
lius1984 2009-05-20
  • 打赏
  • 举报
回复
ffmpeg为了支持最多格式 只是用av_read_frame实现了个音视频同步的框架而已,但完全照他的方式 效果肯定不好 。 另外你为什么要dump出音视频文件再同步? 可以搞个缓冲区试试。 当然这是流媒体播放器的思路了 呵呵
rotus 2009-05-20
  • 打赏
  • 举报
回复
typedef struct tag_VSTREAM_S
{
HI_U8 pVBuffer[size2];
HI_U64 pts;
HI_U32 len; // 这个长度是干嘛用的?
}VSTREAM_S,*pVSTREAM_S;


typedef struct tag_VSTREAM_S
{
HI_U8* pVBuffer; //用动态内存分配
HI_U64 pts;
HI_U32 bufferLen;
}VSTREAM_S,*pVSTREAM_S;

可以参考TCP/IP 协议的处理。
warsour 2009-05-20
  • 打赏
  • 举报
回复
参考ffplay的定义的结构,用的是队列~
你可以看看AVPacketList这个结构~
ljinchi 2009-05-19
  • 打赏
  • 举报
回复
谢谢各位!
另外,我需要对生成的音、视频文件分别加入时间戳信息。以便音视频文件在播放时,能进行同步。
//ffmpeg中定义的结构体
typedef struct AVPacket {
int64_t pts; ///< presentation time stamp in time_base units
int64_t dts; ///< decompression time stamp in time_base units
uint8_t *data;
int size;
int stream_index;
int flags;
int duration; ///< presentation duration in time_base units (0 if not available)
void (*destruct)(struct AVPacket *);
void *priv;
int64_t pos; ///< byte position in stream, -1 if unknown
} AVPacket;

//自定义结构体
typedef struct tag_ASTREAM_S
{
HI_U8 pABuffer[size1];
HI_U64 pts;
HI_U32 len;
}ASTREAM_S,*pASTREAM_S;


typedef struct tag_VSTREAM_S
{
HI_U8 pVBuffer[size2];
HI_U64 pts;
HI_U32 len;
}VSTREAM_S,*pVSTREAM_S;

使用如上代码,当执行av_read_frame(pFormatCtx, &packet)后,把packet中的pts,size,data分别保存到视频结构体(或音频结构体)中,然后,在音、视频播放线程中,通过读取时间戳信息进行控制同步,但pABuffer[size1]和pVBuffer[size2]中的size1和size2要怎么确定?,从packet结构中获得的size会一直变化,而且很大。谢谢。
UDX协议 2009-05-14
  • 打赏
  • 举报
回复
Ffmpeg sdk中有详细的同步代码,你可以借见。


不同的文件做同步,肯定需要手动。
因为,起点不一样,至少需要手动去对齐。
warsour 2009-05-14
  • 打赏
  • 举报
回复
写包的时候pkt.pts就是控制同步的,这个必须弄对~
jinlking 2009-05-14
  • 打赏
  • 举报
回复
理论上是对的但是
pts不是真正的时间
pts *= av_q2d(is->video_st->time_base);
还要与一个基本的时间单位相乘
ljinchi 2009-05-14
  • 打赏
  • 举报
回复
首先感谢你们的回复,另上面代码,只是简单的把读取到的packet.data写到文件中,即fwrite(packet.data, 1, packet.size, hVideo); 我想问一下,packet中还有其他数据成员packet.pts,packet.dts 是否直接可以用来同步呢?谢谢!
rightorwrong 2009-05-14
  • 打赏
  • 举报
回复
ffplay.c不就是个可以音视同步的播放器么

2,542

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧