[英]Convert audio samples to AVFrame FFmpeg & C++
I really need help with correcting a method that I currently work on.我真的需要帮助来纠正我目前正在研究的方法。 The method should convert and write samples into ac3 file.
该方法应将样本转换并写入 ac3 文件。
Input samples are BYTE* in AV_SAMPLE_FMT_FLT format输入样本为 AV_SAMPLE_FMT_FLT 格式的 BYTE*
For encoder the samples must have AV_SAMPLE_FMT_FLTP format对于编码器,样本必须具有 AV_SAMPLE_FMT_FLTP 格式
bool AddAudioSample(AVFormatContext * pFormatContext, AVStream * pStream, BYTE * audiodata, uint32_t sampleCount, uint64_t devicets)
{
AVCodecContext * pCodecCxt = NULL;
bool res = true;
pCodecCxt = pStream->codec;
AVFrame* pFLTAudioFrame = NULL;
pFLTAudioFrame = av_frame_alloc();
AVFrame* pFLTPAudioFrame = NULL;
pFLTPAudioFrame = av_frame_alloc();
ProcessData(pFLTAudioFrame, pFLTPAudioFrame, (uint8_t *)audiodata, sampleCount, devicets);
swr_convert(pSmplConvertCtx, pFLTPAudioFrame->data, pFLTPAudioFrame->nb_samples, (const uint8_t **)pFLTAudioFrame->data, pFLTAudioFrame->nb_samples);
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = pStream->index;
pkt.data = pAudioEncodeBuffer;
pkt.size = pFLTPAudioFrame->pkt_size;
int gotOutput = 0;
auto ret = avcodec_encode_audio2(pCodecCxt, &pkt, pFLTPAudioFrame, &gotOutput);
if (ret < 0)
{
exit(1);
}
if (gotOutput)
{
pkt.pts = av_rescale_q(pCodecCxt->coded_frame->pts, pCodecCxt->time_base, pStream->time_base);
ret = av_interleaved_write_frame(pFormatContext, &pkt);
if (ret < 0)
{
exit(1);
}
}
return res;
}
void ProcessData(AVFrame *inputframe, AVFrame *outputFrame, uint8_t* data, uint32_t sample_count, uint64_t device_ts)
{
inputframe->nb_samples = sample_count;
inputframe->format = AV_SAMPLE_FMT_FLT;
inputframe->sample_rate = mWFX->nSamplesPerSec;
inputframe->channels = mWFX->nChannels;
inputframe->pkt_size = sample_count*mWFX->nBlockAlign;
av_samples_fill_arrays(inputframe->data, inputframe->linesize, data, mWFX->nChannels, sample_count, AV_SAMPLE_FMT_FLT, 1);
outputFrame->nb_samples = inputframe->nb_samples;
outputFrame->format = AV_SAMPLE_FMT_FLTP;
outputFrame->sample_rate = inputframe->sample_rate;
outputFrame->channels = inputframe->channels;
outputFrame->pkt_size = sample_count*mWFX->nBlockAlign;
av_samples_fill_arrays(outputFrame->data, outputFrame->linesize, pAudioEncodeBuffer, mWFX->nChannels, sample_count, AV_SAMPLE_FMT_FLTP, 1);
}
Here is the context resampling setting and calculation for buffer packet:这是缓冲区数据包的上下文重采样设置和计算:
pSmplConvertCtx = swr_alloc();
if (!pSmplConvertCtx)
{
fprintf(stderr, "Could not allocate resampler context\n");
exit(1);
}
av_opt_set_int (pSmplConvertCtx, "in_channel_count", pCodecCxt->channels, 0);
av_opt_set_int (pSmplConvertCtx, "in_sample_rate", pCodecCxt->sample_rate, 0);
av_opt_set_sample_fmt(pSmplConvertCtx, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
av_opt_set_int (pSmplConvertCtx, "out_channel_count", pCodecCxt->channels, 0);
av_opt_set_int (pSmplConvertCtx, "out_sample_rate", pCodecCxt->sample_rate, 0);
av_opt_set_sample_fmt(pSmplConvertCtx, "out_sample_fmt", pCodecCxt->sample_fmt, 0);
if ((swr_init(pSmplConvertCtx)) < 0)
{
fprintf(stderr, "Failed to initialize the resampling context\n");
exit(1);
}
nSizeAudioEncodeBuffer = av_samples_get_buffer_size(NULL, pCodecCxt->channels, pCodecCxt->sample_rate, pCodecCxt->sample_fmt, 1);
if (pAudioEncodeBuffer == NULL)
{
pAudioEncodeBuffer = (uint8_t * )av_malloc(nSizeAudioEncodeBuffer);
}
Here is the process function:这是function的过程:
process_data(AVFrame *frame, uint8_t* data, uint32_t sample_count, uint64_t device_ts)
{
int sample_size = _bit_per_sample / 8 * _channel_num;
//wasapi time unit is 100ns,so time base is NS_PER_SEC
frame->pts = _use_device_ts ? device_ts * 100 : av_gettime_relative();
if(_use_device_ts == false)
frame->pts -= (int64_t)sample_count * NS_PER_SEC / (int64_t)_sample_rate;
frame->pkt_dts = frame->pts;
frame->nb_samples = sample_count;
frame->format = _fmt;
frame->sample_rate = _sample_rate;
frame->channels = _channel_num;
frame->pkt_size = sample_count*sample_size;
av_samples_fill_arrays(frame->data, frame->linesize, data, _channel_num, sample_count, _fmt, 1);
if (_on_data) _on_data(frame, _cb_extra_index);
}
for more details,you can follow https://github.com/peilinok/screen-recorder更多详情可以关注https://github.com/peilinok/screen-recorder
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.