FFMPEG学习(三)ffmpeg+SDL2.0制作简单的视频播放器(图像+声音)

本文基于FFMPEG和SDL2.0,介绍如何制作一个简单的视频播放器,包括图像和声音的播放。在上一篇文章的基础上增加了声音的支持。目前遇到的问题是音频与视频不同步,以及SDL图像刷新时的卡顿问题。
摘要由CSDN通过智能技术生成

FFMPEG 学习(二) ffmpe+SDL2.0制作简单的播放器(基本流程梳理)写的播放程序,仅仅支持图像的播放。这次我们把声音加上

参考文章:

http://blog.yundiantech.com/?log=blog&id=10

 在播放图像的基础上,我们单独通过SDL播放了声音。入上面的图片。结合下面的代码。屡一下audio部分代码的思路

1、首先开启了SDL 的audio设备。callback中等待播放数据,播放的数据来自于队列。

2、读取流、放在队列中。

3、解码程序等待队列中有数据,然后解析,copy到SDL 的audio buf中

总之:流读取到了才有数据方到队列,队列有数据才能解码,解码了才有数据copy到buf,buf里有数据,audio设备才有声音输出

 

 一、源码

/* ************************************************************************
 *       Filename:  audio_demo.c
 *    Description:  
 *        Version:  1.0
 *        Created:  2020年05月25日 21时38分10秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:  YOUR NAME (), 
 *        Company:  
 * ************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
    //#include <libavcodec/avcodec.h>
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/pixfmt.h>
    #include <libswscale/swscale.h>

    #include <SDL.h>
    #include <SDL_audio.h>
    #include <SDL_types.h>
    #include <SDL_name.h>
    #include <SDL_main.h>
    #include <SDL_config.h>
    #include <SDL2/SDL_thread.h>
#ifdef __cplusplus
};
#endif
#include <stdio.h>

//Refresh
#define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)
#define SFM_PLAY_END_EVENT (SDL_USEREVENT + 2)
 


//先按照提供的acc文件播放,后续修改
#define SDL_AUDIO_BUFFER_SIZE 1024
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
#define PLAY_REFRESH_TIME	10				//刷新时间间隔

typedef struct PacketQueue {
    AVPacketList *first_pkt, *last_pkt;		//首尾指针
    int nb_packets;				//包个数
    int size;					//队列大小
    SDL_mutex *mutex;				//队列互斥锁
    SDL_cond *cond;				//队列全局变量
} PacketQueue;

//SDL播放回调
void audio_callback(void *userdata, Uint8 *stream, int len);
//播放流队列初始化
void packet_queue_init(PacketQueue *q);
//播放流添加入队列
int packet_queue_put(PacketQueue *q, AVPacket *pkt);
//播放流出队列
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block);
//从流中解码音频数据
int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size);
///显示视频帧
void Video_Display_To_Window(
								AVPacket 		*packet,		//包
								AVFrame 		*pFrame, 		//流
								AVFrame 		*pFrameYUV, 	//YUV流
								AVCodecContext 	*pCodecCtx,		//解码上下文
								SDL_Texture    	*bmp,			//显示句柄
								SDL_Renderer   	*renderer,		//渲染器句柄
								struct SwsContext *img_convert_ctx,//转码数据
								SDL_Rect 		rect			//显示区域
								);

int sfp_refresh_thread(void *opaque);	//SDL新线程入口			
int thread_exit=0;

// 分配解码过程中的使用缓存
//AVFrame* audioFrame = avcodec_alloc_frame();
AVFrame *audioFrame = NULL;
PacketQueue *audioq = NULL;

#undef main
int main(int argc, char *argv[])
{
	AVFormatContext	*pFormatCtx;				//视频上下文
	AVCodecContext	*pCodecCtx, *videoCodeCtx;				//解码上下文
	int				i, audioindex, videoindex;
	AVCodec			*pCodec, *videoCodec;		//解码器
	AVPacket 		*packet, *VideoPacket;			//打包的流数据
	AVFrame 		*FrameAudio, *FrameVideo, *FrameYUV;
	uint8_t* out_buffer;
	int numBytes;

	//========SDL==========
	//SDL---------------------------
	int screen_w=0,screen_h=0;
	SDL_Window *screen; 
	SDL_Renderer* sdlRenderer;
	SDL_Texture* sdlTexture;
	SDL_Rect sdlRect;
	int ret, got_picture;
	struct SwsContext *img_convert_ctx;
	//=========SDL===end===
	//char *filename = "./video2.mp4";	
	
	//SDL thread
	SDL_Thread *video_tid;
	SDL_Event event; 

	if(1 == argc)
	{
		printf("%s:%d parameter error \n", __func__, __LINE__);
		return -1;
	}

	audioFrame = av_frame_alloc();
	//audioFrame = avcodec_alloc_frame();

//&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值