ffmpeg-3.1.5音频播放代码

来源:互联网 发布:行动监管软件是诈骗 编辑:程序博客网 时间:2024/04/29 13:33

本文代码在雷博的基础上进行了略微修改,实现播放音频的功能。

使用ffmpeg-3.1.5 + SDL2

雷博的代码链接:http://blog.csdn.net/leixiaohua1020/article/details/38979615

修改了两个地方:(1)使用了新版本的ffmpeg API。(2)更改了部分变量的赋值,使程序能够适应各种音频序列。

代码还不是完全理解,先记录下来。

/**实现音频解码和播放*/#include "stdafx.h"#include <stdio.h>#include <iostream>using namespace std;extern "C"{#include "include\libavcodec\avcodec.h"#include "include\libavformat\avformat.h"#include "include\libswresample\swresample.h"#include "include\SDL2\SDL.h"};#define __STDC_CONSTANT_MACROS #define OUTPUT_PCM 0//Bufferstatic Uint8 *audio_chunk;static Uint32 audio_len;static Uint8 *audio_pos;//callback funcvoid  fill_audio(void *udata, Uint8 *stream, int len){SDL_memset(stream, 0, len);if (audio_len == 0)        /*  Only  play  if  we  have  data  left  */return;len = (len>audio_len ? audio_len : len);   /*  Mix  as  much  data  as  possible  */SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);audio_pos += len;audio_len -= len;}int _tmain(int argc, _TCHAR* argv[]){AVFormatContext *pFormatCtx;AVCodecContext *pCodecCtx;AVCodec *pCodec;int audioStreamIndex;//input audiochar url[] = "test.mp3";#if OUTPUT_PCM//output fileFILE *outputFile = NULL;char *outputFileName = "output.aac";fopen_s(&outputFile, outputFileName, "wb");#endif//init ffmpegav_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();//open input audioif (avformat_open_input(&pFormatCtx, url, NULL, NULL) != 0){cout << "could not open input stream." << endl;return -1;}if (avformat_find_stream_info(pFormatCtx,NULL) < 0){cout << "could not find stream information." << endl;return -1;}//print input audio infocout << "--------------------- audio info ---------------------" << endl;av_dump_format(pFormatCtx, 0, url, false);cout << "------------------------------------------------------" << endl;//find audioStreamIndexaudioStreamIndex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, NULL);if (audioStreamIndex < 0){cout << "could not found a audio stream." << endl;return -1;}//find codecpCodecCtx = avcodec_alloc_context3(NULL);if (pCodecCtx == NULL){cout << "could not allocate audio AVCCodecContext." << endl;return -1;}avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioStreamIndex]->codecpar);pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL){cout << "Codec not found." << endl;return -1;}//open codecif (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){cout << "could not open codec." << endl;return -1;}//out audio paramuint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;int out_nb_samples = pCodecCtx->frame_size;//number of samples per channels in an audio frameAVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;int out_sample_rate = pCodecCtx->sample_rate;int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);//the number of channels//out buffer sizeint out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1);uint8_t *out_buffer = (uint8_t *)av_malloc(out_buffer_size);//SDLif (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){cout << "could not initialize SDL - " << SDL_GetError << endl;return -1;}SDL_AudioSpec wanted_spec;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;//open the audio device with the desired parametersif (SDL_OpenAudio(&wanted_spec, NULL) < 0){cout << "could not open audio." << endl;return -1;}printf("Bitrate:\t %3d\n", pFormatCtx->bit_rate);printf("Decoder Name:\t %s\n", pCodecCtx->codec->long_name);printf("Channels:\t %d\n", pCodecCtx->channels);printf("Sample per Second\t %d \n", pCodecCtx->sample_rate);//FIX:some codec's context information is missingint64_t in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);//Swr  struct SwrContext *au_convert_ctx;au_convert_ctx = swr_alloc();au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate, in_channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);swr_init(au_convert_ctx);//pre decodeAVPacket *packet = (AVPacket*)malloc(sizeof(AVPacket));av_init_packet(packet);AVFrame *pFrame;pFrame = av_frame_alloc();//Play  SDL_PauseAudio(0);int index = 0;while (av_read_frame(pFormatCtx, packet) >= 0){if (packet->stream_index == audioStreamIndex){if (avcodec_send_packet(pCodecCtx, packet) != 0){printf("input AVPacket to audio decoder failed!\n");return -1;}while (0 == avcodec_receive_frame(pCodecCtx, pFrame)){swr_convert(au_convert_ctx, &out_buffer, out_buffer_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++;audio_chunk = (Uint8*)out_buffer;audio_len = out_buffer_size;audio_pos = audio_chunk;while (audio_len > 0)SDL_Delay(1);#if OUTPUT_PCM//wirte filefwrite(out_buffer, 1, out_buffer_size, outputFile);#endif OUTPUT_PCM}}av_packet_unref(packet);}//freeswr_free(&au_convert_ctx);SDL_CloseAudio();SDL_Quit();av_free(out_buffer);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);#if OUTPUT_PCMfclose(outputFile);#endifreturn 0;}



0 0
原创粉丝点击