主机环境:Windows XP
SDL版本:SDL2-2.0.3
ffmpeg版本:ffmpeg.2.4
ffmpeg库版本:ffmpeg-20140916-git-b76d613-win32-dev.7z、ffmpeg-20140916-git-b76d613-win32-shared.7z
开发环境:CodeBlocks13.12
结合之前的音频播放器和视频播放器代码,如下
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
#include <libavutil/mem.h>
#include <libswscale/swscale.h>
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <SDL2/SDL.h>
#include <stdbool.h>
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define rmask 0xff000000
#define gmask 0x00ff0000
#define bmask 0x0000ff00
#define amask 0x000000ff
#else
#define rmask 0x000000ff
#define gmask 0x0000ff00
#define bmask 0x00ff0000
#define amask 0xff000000
#endif
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
typedef struct PacketQueue
{
AVPacketList *first_pkt, *last_pkt;//首尾指针
int nb_packets;//包数
int size;//包中的字节数
SDL_mutex *mutex;//互斥变量
SDL_cond *cond;//条件变量
} PacketQueue;
PacketQueue audioQ;
struct SwrContext *audio_swr_ctx;//重采样上下文
uint64_t out_ch_layout = AV_CH_LAYOUT_STEREO;//输出声道布局
int out_nb_samples = 1024;
enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;//输出源采样格式
int out_rate = 44100;//输出源的采样率
int out_nb_channels = 0;//得到通道数
int out_buffer_size = 0;//输出源的缓存大小
void packet_queue_init(PacketQueue *pq)
{
memset(pq,0,sizeof(PacketQueue));//清空结构体
pq->mutex = SDL_CreateMutex();//创建一个互斥量
pq->cond = SDL_CreateCond();//创建一个条件量
}
/**
first_pkt指针指向第一个数据包元素,每次更新last_pkt指针,指向最后一个数据包元素
**/
int packet_queue_put(PacketQueue *pq, AVPacket *pkt)
{
AVPacketList *pktlist;
if(av_dup_packet(pkt) < 0)
{
printf("dup packet error!\n");
//将数据拷贝至私有缓存中
return -1;
}
pktlist = av_malloc(sizeof(AVPacketList));
if(!pktlist)
{
return -1;
}
pktlist->pkt = *pkt;//初始化列表元素
pktlist->next = NULL;//初始化列表元素
SDL_LockMutex(pq->mutex);//上锁
if(!pq->last_pkt)
{
//如果last_pkt指针为空,则重新链接first_pkt指针至新建的pktlist元素
pq->first_pkt = pktlist;
}
else
{
//如果last指针不为空,则将pktlist元素添加到last链表末端
pq->last_pkt->next = pktlist;
}
pq->last_pkt = pktlist;//将last_pkt指针指向新添加的pktlist元素,移动last_pkt指针
pq->nb_packets++;//数据包个数增加
pq->size+=pktlist->pkt.size;//数据大小增加
SDL_CondSignal(pq->cond);//通知条件变量
SDL_UnlockMutex(pq->mutex);//解锁
return 0;
}
int quit = 0;
/**
从队列中取出一个数据包block:标记是否以阻塞方式取数据包
**/
static int packet_queue_get(PacketQueue *pq, AVPacket *ptk, int block)
{
AVPacketList *pktlist;
int ret;
SDL_LockMutex(pq->mutex);//上锁
static bool flag = fal