一.包含头文件和库文件

修改CMakeLists

# swresample
add_library(swresample SHARED IMPORTED)
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${FF}/libswresample.so)

更新target_link_libraries

target_link_libraries( # Specifies the target library.
native-lib
avcodec
avformat
avutil
swscale
swresample # Links the target library to the log library
# included in the NDK.
${log-lib} )

在代码中包含头文件 #include <libswresample/swresample.h>

二.相关函数说明

a)

SwrContext *swr_alloc(void);  // 分配重采样的上下文。

SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, AVSampleFormat out_sample_fmt, int out_sample_rate

, int64_t in_ch_layout, AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx

);

参数1:重采样上下文

参数2:输出的layout, 如:5.1声道…

参数3:输出的样本格式。Float, S16, S24

参数4:输出的样本率。可以不变。

参数5:输入的layout。

参数6:输入的样本格式。

参数7:输入的样本率。

参数8,参数9,日志,不用管,可直接传0

针对音频的播放速度,可以通过样本率的改变而改变。

int swr_init(struct SwrContext *s);                       // 初始化上下文

void swr_free(struct SwrContext **s);                  // 释放上下文空间。

b)

swr_convert()

针对每一帧音频的处理。把一帧帧的音频作相应的重采样

int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count);

参数1:音频重采样的上下文

参数2:输出的指针。传递的输出的数组

参数3:输出的样本数量,不是字节数。单通道的样本数量。

参数4:输入的数组,AVFrame解码出来的DATA

参数5:输入的单通道的样本数量。

三.示例代码

// 初始化像素格式转换上下文
SwsContext *vctx = NULL;
int outWidth = ;
int outHeight = ;
char *rgb = new char[**];
char *pcm = new char[**]; // 初始化音频重采样上下文
SwrContext *actx = swr_alloc();
actx = swr_alloc_set_opts(
actx,
av_get_default_channel_layout(),
AV_SAMPLE_FMT_S16,
ac->sample_rate,
av_get_default_channel_layout(ac->channels),
ac->sample_fmt,
ac->sample_rate,
,
); ret = swr_init(actx);
if (ret != ) {
LOGE("swr_init failed");
} else {
LOGI("swr_init success");
} for (;;) { if (getNowMs() - start >= ) {
LOGI("now decoder fps is: %d", frameCount / );
start = getNowMs();
frameCount = ;
}
int ret = av_read_frame(ic, packet);
if (ret != ) {
LOGE("读取到结尾处");
int pos = * r2d(ic->streams[videoStream]->time_base);
// 改变播放进度
av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
continue;
} // LOGI("Read a Packet. streamIndex=%d, size=%d, pts=%lld, flag=%d",
// packet->stream_index,
// packet->size,
// packet->pts,
// packet->flags
// ); AVCodecContext *cc = vc;
if (packet->stream_index == audioStream) cc = ac;
// 发送到线程中去解码(将packet写入到解码队列当中去)
ret = avcodec_send_packet(cc, packet);
// 清理
int p = packet->pts;
av_packet_unref(packet);
if (ret != ) {
// LOGE("avcodec_send_packet failed.");
continue;
} for(;;) {
// 从已解码成功的数据当中取出一个frame, 要注意send一次,receive不一定是一次
ret = avcodec_receive_frame(cc, frame);
if (ret != ) {
break;
}
if (cc == vc) {
frameCount++;
vctx = sws_getCachedContext(
vctx,
frame->width,
frame->height,
(AVPixelFormat)frame->format,
outWidth,
outHeight,
AV_PIX_FMT_RGBA,
SWS_FAST_BILINEAR,
, ,
);
if (!vctx) {
LOGE("sws_getCachedContext failed!");
} else {
// 开始像素格式转换
uint8_t *data[AV_NUM_DATA_POINTERS] = {};
data[] = (uint8_t *)rgb;
int lines[AV_NUM_DATA_POINTERS] = {};
lines[] = outWidth * ;
int h = sws_scale(
vctx,
(const uint8_t **)frame->data,
frame->linesize,
,
frame->height,
data, lines
);
LOGI("sws_scale = %d", h);
}
} else { // 音频部分
uint8_t *out[] = {};
out[] = (uint8_t *)pcm;
// 音频重采样
int len = swr_convert(
actx,
out,
frame->nb_samples,
(const uint8_t **)frame->data,
frame->nb_samples
);
LOGI("swr_convert = %d", len);
}
// LOGI("Receive a frame.........");
}
} delete rgb;
delete pcm;
05-07 15:11