【音视频开发】变速与硬解码
一、变速
作者在开发过程中需要进行对视频进行变速不变调的开发,于是使用sonic库来实现对应的功能。
sonic库github地址:https://github.com/waywardgeek/sonic
// 判断是否要变速
if (is->useSonic)
{
is->useSonic = !is->useSonic;
if (is->sonic_stream_ready)
{
sonicDestroyStream(is->sncStream);
}
is->sonic_stream_ready = true;
is->sncStream = sonicCreateStream(is->audio_tgt.freq, is->audio_tgt.channels);
sonicSetSpeed(is->sncStream, is->volume_speed);
sonicSetPitch(is->sncStream, 1.0);
sonicSetRate(is->sncStream, 1.0);
}
// 进行了变速
if (is->volume_speed != 1.0 && is->audio_buf)
{
int actual_out_samples = is->audio_buf_size/ (is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt));
int ret;
int num_available_samples = 0;
int out_size = 0;
int sonic_samples = 0;
ret = sonicWriteShortToStream(is->sncStream, (short*)is->audio_buf, actual_out_samples);
num_available_samples = sonicSamplesAvailable(is->sncStream);
out_size = num_available_samples * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
//printf("sonic_size:%d\n", out_size);
av_fast_malloc(&is->sonic_buf, &is->sonic_buf_size, out_size);
if (ret)
{
sonic_samples = sonicReadShortFromStream(is->sncStream, (short*)is->sonic_buf, num_available_samples);
is->audio_buf = is->sonic_buf;
is->audio_buf_size = sonic_samples * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
is->audio_buf_index = 0;
}
}
其中 sonicWriteShortToStream(is->sncStream, (short*)is->audio_buf, actual_out_samples);sonicWriteShortToStream函数需要传入short*参数 因此对其大小要重新进行计算。
二、硬解码
本人使用ffmpegAPI来进行硬解码的初始化
const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index);:根据视频的AVCode,以及影解码器的type(AVHWDeviceType)来获取对应的AVCodecHWConfig 。
int av_hwdevice_ctx_create(AVBufferRef ** device_ctx, enum AVHWDeviceType type,const char *device, AVDictionary *opts, int flags);:创建硬解码设备参数的上下文
int ret = av_hwdevice_ctx_create(&hw_device_buf, type, nullptr, nullptr,0);
if (ret < 0) {
fprintf(stderr, "Failed to create specified HW device.\n");
return ret;
}
//AVCodecContext* avctx 解码器上下文进行绑定
avctx->hw_device_ctx = av_buffer_ref(hw_device_buf);
avctx->get_format = get_hw_format;//绑定获取硬件解码format的回调函数返回参数为AVPixelFormat
** int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);**:将GPU中解码好的数据存放到CPU中