文章目录
简介
学习FFmpeg已经有一段时间了,都是断断续续、零零散散的,没有系统的总结过,为了保证学习效果,决定自己写一个音视频播放器,借着这个项目对FFmpeg进行系统的学习与总结,争取对FFmpeg达到熟练应用的程度。
FFmpeg音视频播放器系列,本着循序渐进的过程,先从最简单的开始,逐步深入到使用QT写出一个带有GUI界面的应用软件。这个项目估计要耗时很长,但愿自己能坚持下来。
先对这个项目确定一个小目标吧:
1、模仿市面上的播放器界面使用QT完成GUI
2、可以选择单独播放视频或者音频
3、可以播放网络视频流
4、可以录制音频与视频
5、可以播放摄像头视频
好了,就这么多,多了怕自己完成不了。
自己的开发平台如下:
Ubuntu16.04
FFmpeg:4.0.2
SDL2:2.0.8
QT:5.12.1
FFmpeg的学习我基本上是基于雷神的博客,再次他致敬!他的FFmpeg博客地址在此先行贴出:
https://blog.csdn.net/leixiaohua1020/column/info/ffmpeg-devel
FFMPEG+SDL的视频播放器
雷神也有这篇博客,不过他是将视频与音频分开的,带有音频的视频在播放时,只能播放视频而没有声音,因此本篇就先进行一下综合,写出一个基于FFMPEG+SDL的简单视频播放器,可以同时播放音频与视频,可能会有音视频播放同步的问题,待到下一篇进行总结与说明。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __STDC_CONSTANT_MACROS
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavutil/time.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
};
#endif
#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
static Uint8 *audio_chunk;
static Sint32 audio_len;
static Uint8 *audio_pos;
//Refresh Event
#define SFM_REFRESH_VIDEO_EVENT (SDL_USEREVENT + 1)
#define SFM_REFRESH_AUDIO_EVENT (SDL_USEREVENT + 2)
#define SFM_BREAK_EVENT (SDL_USEREVENT + 3)
int thread_exit=0;
int thread_pause=0;
int sfp_refresh_thread(void *opaque){
thread_exit=0;
thread_pause=0;
while (!thread_exit)
{
if(!thread_pause)
{
SDL_Event event;
event.type = SFM_REFRESH_VIDEO_EVENT;
SDL_PushEvent(&event);
}
SDL_Delay(40);
}
thread_exit=0;
thread_pause=0;
//Break
SDL_Event event;
event.type = SFM_BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
/* The audio function callback takes the following parameters:
* stream: A pointer to the audio buffer to be filled
* len: The length (in bytes) of the audio buffer
*/
void fill_audio(void *udata,Uint8 *stream,int len){
//SDL 2.0
SDL_memset(stream, 0, len);
if(audio_len==0)
return;
len=(len>audio_len?audio_len:len); /* Mix as much data as possible */
SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
audio_pos += len;
audio_len -= len;
}
int main(int argc, char* argv[])
{
AVFormatContext *pFormatCtx;
AVCodecContext *pVideoCodecCtx, *pAudioCodecCtx;
AVCodec *pVideoCodec, *pAudioCodec;
AVFrame *pVideoFrame,*pAudioFrame,*pFrameYUV;
unsigned char *pVideoOutBuffer, *pAudioOutBuffer;
//AVPacket *pVideoPacket, *pAudioPacket;
AVPacket *Packet;
int i, ret, GotVideoPicture