各位兄弟,请问如何利用Ffmpeg进行音视频同步,非常感谢!(有代码)
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx;
int i, videoStream;
int audioStream;
AVPacketpacket;
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文件同步播放呢。非常感谢!
[解决办法]
Ffmpeg sdk中有详细的同步代码,你可以借见。
不同的文件做同步,肯定需要手动。
因为,起点不一样,至少需要手动去对齐。
[解决办法]
ffplay.c不就是个可以音视同步的播放器么
[解决办法]
理论上是对的但是
pts不是真正的时间
pts *= av_q2d(is->video_st->time_base);
还要与一个基本的时间单位相乘
[解决办法]
写包的时候pkt.pts就是控制同步的,这个必须弄对~
[解决办法]
参考ffplay的定义的结构,用的是队列~
你可以看看AVPacketList这个结构~
[解决办法]
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 协议的处理。
[解决办法]
ffmpeg为了支持最多格式 只是用av_read_frame实现了个音视频同步的框架而已,但完全照他的方式 效果肯定不好 。 另外你为什么要dump出音视频文件再同步? 可以搞个缓冲区试试。 当然这是流媒体播放器的思路了 呵呵
------解决方案--------------------
网上有教程,http://www.dranger.com/ffmpeg/tutorial05.html
这个教程是用ffmpeg+SDL来实现视音频的插放与同步,同步还是要用到AVPacket的PTS和DTS、
[解决办法]
一般有三种办法
1.以音频为主进行同步
2.以视频为主进行同步
3.以一个外部参考时钟为同步
你可以参考下ffmpeg下的ffplay来做,还有
http://www.dranger.com/ffmpeg/tutorial05.html 和
http://www.dranger.com/ffmpeg/tutorial04.html
具体如何实现还是要靠自己研究清楚代码后来解决的.