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();
//&#