FFMPEG学习----使用SDL构建音频播放器
ffmpeg版本:ffmpeg-20160413-git-0efafc5
#include <stdio.h>
#include <stdlib.h>
#include <string.h> extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "SDL.h"
}; #define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio Uint32 audio_len;//音频数据大小
Uint8 *audio_pos;//指向音频数据的指针 //回调函数
void fill_audio(void *userdata, Uint8 *stream, int len)
{
//SDL 2.0
SDL_memset(stream, 0, len);
if (audio_len == 0)
{
return;
} len = (len > audio_len ? audio_len : len); SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
audio_pos += len;
audio_len -= len;
} int main(int argc, char* argv[])
{
//FFmpeg
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVPacket packet;
AVFrame *pFrame;
struct SwrContext *au_convert_ctx;
int got_picture;
int audioIndex; //SDL
uint8_t *out_buffer;
SDL_AudioSpec wanted_spec;
int index = 0; char filepath[1024] = "";
printf("Usage: player.exe *.mp3\n");
if (argc == 2)
{
strcpy(filepath, argv[1]);
}
else
{
printf("Could not find a audio file\n");
return -1;
} av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)
{
printf("Couldn't open input stream.\n");
return -1;
} if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\n");
return -1;
} av_dump_format(pFormatCtx, -1, filepath, 0); audioIndex = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
//AVStream->codec不推荐使用
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioIndex = i;
break;
}
}
if (audioIndex == -1)
{
printf("Didn't find a audio stream.\n");
return -1;
} //------------------------------------------------
//新版本:分配、填充AVCodecContext
pCodecCtx = avcodec_alloc_context3(NULL);
if (pCodecCtx == NULL)
{
printf("Could not allocate AVCodecContext\n");
return -1;
} if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioIndex]->codecpar) < 0)
{
printf("Could not initialize AVCodecContext\n");
return -1;
}
//------------------------------------------------ pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
printf("Codec not found.\n");
return -1;
} if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)
{
printf("Could not open codec.\n");
return -1;
} //Out Audio Param
uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
//nb_samples: AAC-1024 MP3-1152
int out_nb_samples = pCodecCtx->frame_size;
AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
int out_sample_rate = 44100;
int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
//Out Buffer Size
int out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1); out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
pFrame = av_frame_alloc(); //Init
if (SDL_Init(SDL_INIT_AUDIO))
{
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
//SDL_AudioSpec
wanted_spec.freq = out_sample_rate;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.channels = out_channels;
wanted_spec.silence = 0;
wanted_spec.samples = out_nb_samples;
wanted_spec.callback = fill_audio;
wanted_spec.userdata = pCodecCtx; if (SDL_OpenAudio(&wanted_spec, NULL) < 0)
{
printf("can't open audio.\n");
return -1;
} au_convert_ctx = swr_alloc();
au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate,
pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);
swr_init(au_convert_ctx); //Play
SDL_PauseAudio(0); while (av_read_frame(pFormatCtx, &packet) >= 0)
{
if (packet.stream_index == audioIndex)
{
if (avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, &packet) < 0)
{
printf("Error in decoding audio frame.\n");
return -1;
}
if (got_picture)
{
swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples);
printf("index:%5d\t pts:%lld\t packet size:%d\n", index, packet.pts, packet.size);
index++;
} while (audio_len > 0)//Wait until finish
{
SDL_Delay(1);
} //Audio buffer length
audio_len = out_buffer_size;
audio_pos = (Uint8 *)out_buffer; }
av_packet_unref(&packet);
} swr_free(&au_convert_ctx);
SDL_CloseAudio();//Close SDL
SDL_Quit();
av_free(out_buffer);
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
FFMPEG学习----使用SDL构建音频播放器的更多相关文章
- 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)
===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...
- 最简单的基于FFMPEG+SDL的音频播放器 ver2 (採用SDL2.0)
===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...
- FFMPEG学习----使用SDL构建视频播放器
#include <stdio.h> #include <string.h> extern "C" { #include "libavcodec/ ...
- ffmpeg+SDL2实现的音频播放器V2.0(无杂音)
1. 前言 目前为止,学习了并记录了ffmpeg+SDL2显示视频以及事件(event)的内容. 这篇中记录ffmpeg+SDL2播放音频,没加入事件处理. 接下来加入事件处理并继续学习音视频同步,再 ...
- 11.QT-ffmpeg+QAudioOutput实现音频播放器
1.前言 由于QAudioOutput支持的输入数据必须是原始数据,所以播放mp3,WAV,AAC等格式文件,需要解封装后才能支持播放. 而在QT中,提供了QMediaPlayer ...
- IOS开发之简单音频播放器
今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...
- 基于c开发的全命令行音频播放器
cmus是一个内置了音频播放器的强大的音乐文件管理器.用它的基于ncurses的命令行界面,你可以浏览你的音乐库,并从播放列表或队列中播放音乐,这一切都是在命令行下. Linux上安装cmus 首先, ...
- HTML5 音频播放器-Javascript代码(短小精悍)
直接上干货咯! //HTML5 音频播放器 lzpong 2015/01/19 var wavPlayer = function () { if(window.parent.wavPlayer) re ...
- 【jquery】一款不错的音频播放器——Amazing Audio Player
前段时间分享了一款视频播放器,点击这里.今天介绍一款不错的音频播放器——Amazing Audio Player. 介绍: Amazing Audio Player 是一个使用很方便的 Windows ...
随机推荐
- Ceph14.2.5 RBD块存储的实战配置和详细介绍,不看后悔! -- <3>
Ceph RBD介绍与使用 RBD介绍 RBD即RADOS Block Device的简称,RBD块存储是最稳定且最常用的存储类型.RBD块设备类似磁盘可以被挂载. RBD块设备具有快照.多副本.克隆 ...
- 「Luogu P3931」SAC E#1 - 一道难题 Tree 解题报告
圆原题面 我环顾四周,发现大佬们的写法都好高端! 比较差劲的我,只能交上一份DFS的题解 思路: DFS(当然了,其他算法也行) 要想切断叶子节点到根节点的连接 就是在叶子节点和根节点之间砍掉一条边 ...
- 1043 输出PATest (20 分)C语言
给定一个长度不超过 10^4的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest- 这样的顺序输出,并忽略其它字符.当然,六种字符的个数不一定是一样多的,若某种字符已经输 ...
- array_diff 大bug
$aa = array("手机号", "first","keyword1","keyword2","keywo ...
- AcWing 247. 亚特兰蒂斯 | 扫描线
传送门 题目描述 有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述. 其中一些甚至包括岛屿部分地图. 但不幸的是,这些地图描述了亚特兰蒂斯的不同区域. 您的朋友Bill必须知道地图的总面积. 你自 ...
- JDK12 的下载和没有jre的解决及环境配置
一.下载直接在官网上下载并点击安装即可,步骤省.jdk12下载中途已经没有跳出窗口下载jre的过程了,需要手动生成jre. 二.没有jre的解决:1.cmd 2.切换到jdk的安装目录,执行命令:bi ...
- Java之String类用法总结
String类概述: 1.String类代表字符串.Java 程序中的所有字符串字面值(如"abc")都作为此类的实例实现. 2.String是一个final类,代表不可变的字符序 ...
- Helm, 在Kubernetes中部署应用的利器
一.背景 Kubernetes(k8s)是一个基于容器技术的分布式架构领先方案.它在Docker技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提高了大规模容器 ...
- Java小白集合源码的学习系列:ArrayList
ArrayList源码学习 本文基于JDK1.8版本,对集合中的巨头ArrayList做一定的源码学习,将会参考大量资料,在文章后面都将会给出参考文章链接,本文用以巩固学习知识. ArrayList的 ...
- CVE-2019-0708远程桌面服务远程执行代码漏洞exp利用过程
CVE-2019-0708远程桌面服务远程执行代码漏洞 上边这洞是啥我就不多说了,描述类的自行百度. 受影响系统版本范围: Windows Server 2008 R2 Windows Server ...