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构建音频播放器的更多相关文章

  1. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  2. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (採用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  3. FFMPEG学习----使用SDL构建视频播放器

    #include <stdio.h> #include <string.h> extern "C" { #include "libavcodec/ ...

  4. ffmpeg+SDL2实现的音频播放器V2.0(无杂音)

    1. 前言 目前为止,学习了并记录了ffmpeg+SDL2显示视频以及事件(event)的内容. 这篇中记录ffmpeg+SDL2播放音频,没加入事件处理. 接下来加入事件处理并继续学习音视频同步,再 ...

  5. 11.QT-ffmpeg+QAudioOutput实现音频播放器

    1.前言      由于QAudioOutput支持的输入数据必须是原始数据,所以播放mp3,WAV,AAC等格式文件,需要解封装后才能支持播放.      而在QT中,提供了QMediaPlayer ...

  6. IOS开发之简单音频播放器

    今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...

  7. 基于c开发的全命令行音频播放器

    cmus是一个内置了音频播放器的强大的音乐文件管理器.用它的基于ncurses的命令行界面,你可以浏览你的音乐库,并从播放列表或队列中播放音乐,这一切都是在命令行下. Linux上安装cmus 首先, ...

  8. HTML5 音频播放器-Javascript代码(短小精悍)

    直接上干货咯! //HTML5 音频播放器 lzpong 2015/01/19 var wavPlayer = function () { if(window.parent.wavPlayer) re ...

  9. 【jquery】一款不错的音频播放器——Amazing Audio Player

    前段时间分享了一款视频播放器,点击这里.今天介绍一款不错的音频播放器——Amazing Audio Player. 介绍: Amazing Audio Player 是一个使用很方便的 Windows ...

随机推荐

  1. vux中x-input在安卓手机输入框的删除按钮(@on-click-clear-icon)点击没反应

    首先看你自己的的版本好,如果在2.6.9以上,我是在git上找到的解决办法,记录一下,希望可以帮到有需要的小伙伴. 在项目中找 node_modules > vux > x-input & ...

  2. Linux上查找最大文件的 3 种方法

    有时候我们在系统上安装了数十个应用程序,随着使用时间的推移,许多文件变得越来越大,从而导致磁盘空间越来越小.那么问题来了,如何找到系统上这些大文件,然后进行一番磁盘空间清理呢,这篇文章就此介绍几种查找 ...

  3. Go网络编程

    概述 网络协议 从应用的角度出发,协议可理解为"规则",是数据传输和数据的解释的规则.假设,A.B双方欲传输文件.规定: 第一次,传输文件名,接收方接收到文件名,应答OK给传输方: ...

  4. 「USACO15FEB」Censoring (Silver) 审查(银) 解题报告

    题面 就是让你--在字符串A中,如果字符串B是A的子串,那么就删除在A中第一个出现的B,然后拼接在一起,一直重复上述步骤直到B不再是A的子串 |A|\(\le 10^6\) 思路: KMP+栈 1.由 ...

  5. 实操教程丨如何在K8S集群中部署Traefik Ingress Controller

    注:本文使用的Traefik为1.x的版本 在生产环境中,我们常常需要控制来自互联网的外部进入集群中,而这恰巧是Ingress的职责. Ingress的主要目的是将HTTP和HTTPS从集群外部暴露给 ...

  6. C#反射与特性(五):类型成员操作

    目录 1,MemberInfo 1.1 练习-获取类型的成员以及输出信息 1.2 MemberType 枚举 1.3 MemberInfo 获取成员方法并且调用 1.4 获取继承中方法的信息(Decl ...

  7. 【转】DB2数据库编目的概念以及对其的正确解析

    此文章主要向大家描述的是DB2数据库编目的概念以及对DB2数据库编目的概念的正确理解,在DB2中编目(catalog)这个单词看似很难理解,我自己当初在学习DB2数据库的时候也常常被这个编目搞的很不明 ...

  8. Airbnb如何应用AARRR策略成为全球第一民宿平台

    案例背景 基于房东和租客的痛点构建短租平台,但困于缓慢增长 2007年,住在美国旧金山的两位设计师——BrianChesky与Joe Gebbia正在为他们付不起房租而困扰.为了赚点外块,他们计划将阁 ...

  9. 在IIS上发布netcore项目

    保证电脑上有.net core sdk或者.net core runtime; 需要安装AspNetCoreModule托管模块:DotNetCore.2.0.5-WindowsHosting.exe ...

  10. Spring Boot2 系列教程 (八) | 配置日志

    前言 如题,今天介绍 springboot 默认日志的配置. 默认日志 Logback 默认情况下,Spring Boot 用 Logback 来记录日志,并用 INFO 级别输出到控制台.如果你在平 ...