文件名用const char * 字符指针就行,赋值为一个“”引起的字符串。
文件用FILE结构体
打开文件用fopen,关闭文件用fclose,写入文件fwrite
ffmpeg也有自己的打开和关闭的函数
作者这个文章里头,分析的ffmpeg的那些代码的用意很好,比教程的分析好理解多了。
(1)读取(2)分离音频视频(3)解码(4)播放
作者在实践中发现了,ffmpeg采用队列来保存包的高明之处。
同步的问题,在这篇文章,没有得到解决。因为没谈及到同步的机制。
发帖人在这篇文章中,大量使用了ffmpeg的代码,这样可以节省很多时间。
作者好像是有pc端和下位机端的。
文件在pc端,读取出来文件以及文件的诸多信息之后,在下位机端解码。
音频和视频,是分别读取的,使用了两个不同的线程,下位机接受和解码也使用了两个线程。
作者没有交代如何显示的,但是肯定不是SDL,他用的是windows上的FFMPEG的SDK来做的。
作者现在亟待要解决的是同步的问题。
他用的是directshow。
====================
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文件同步播放呢。非常感谢! </ Ffmpeg sdk中有详细的同步代码,你可以借见。
不同的文件做同步,肯定需要手动。 因为,起点不一样,至少需要手动去对齐。</ ffplay.c不就是个可以音视同步的播放器么</ 首先感谢你们的回复,另上面代码,只是简单的把读取到的packet.data写到文件中,即fwrite(packet.data, 1, packet.size, hVideo); 我想问一下,packet中还有其他数据成员packet.pts,packet.dts 是否直接可以用来同步呢?谢谢! </< p>
</ 写包的时候pkt.pts就是控制同步的,这个必须弄对~</ 谢谢各位! 另外,我需要对生成的音、视频文件分别加入时间戳信息。以便音视频文件在播放时,能进行同步。 //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会一直变化,而且很大。谢谢。</ 参考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 协议的处理。 </ 有偿跪求基于directshow视频聊天程序,要求,基于directshow,视频可以单向传输,音频要求双向传输。传输前要压缩,有意者联系QQ 35265480 有偿啊,因为很着急
</ 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 具体如何实现还是要靠自己研究清楚代码后来解决的.</ 我进来学习一下。 楼主在TS demux出来存成Video和Audio两个文件的时候,是不是应该把时间戳的信息也保存出来啊,不然的话单独只有一个audio和一个video的数据文件,同步从何谈起啊?</ < mark</ 谢谢各位的建议。
我把上面的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中的音视频同步代码,哪位兄弟能详细分析一下。
关于音视频同步问题,比较急,希望大家能帮帮我,再次谢谢大家。 </ 由于时间比较急,没办法再去仔细研究音视频同步了,公司领导一直在催这个问题,如果哪位兄弟能具体说一下关于如何控制音视频同步问题,我自己来实现它,给予适当的报酬,表达一下心意也是可以的。谢谢。 我的邮箱:ljinchi@163.com QQ:24385971</ 关注,学习学习…
|