Tôi đang làm việc để ghi và phát trực tuyến âm thanh đến máy chủ RTMP tại một thời điểm. Tôi làm việc dưới MacOS (trong Xcode), vì vậy để chụp bộ đệm mẫu âm thanh, tôi sử dụng khung công tác AVFoundation. Nhưng để mã hóa và phát trực tuyến, tôi cần sử dụng bộ mã hóa ffmpeg-API và libfaac. Vì vậy, định dạng đầu ra phải là AAC (để hỗ trợ phát lại luồng trên các thiết bị iOS).Cách mã hóa PCM-âm thanh đã được lấy lại thành AAC bằng cách sử dụng ffmpeg-API khi số lượng mẫu pcm đầu vào không bằng 1024
Và tôi phải đối mặt với vấn đề như vậy: thiết bị ghi âm (trong trường hợp máy ảnh logitech) cung cấp cho tôi bộ đệm mẫu với 512 mẫu LPCM và tôi có thể chọn tốc độ mẫu đầu vào từ 16000, 24000, 36000 hoặc 48000 Hz. Khi tôi đưa các mẫu 512 này tới bộ mã hóa AAC (được định cấu hình cho tỷ lệ mẫu thích hợp), tôi nghe thấy âm thanh chậm và giật chậm và giật (có vẻ giống như pice im lặng sau mỗi khung hình).
Tôi đã tìm ra (có thể tôi sai), bộ mã hóa libfaac đó chỉ chấp nhận khung âm thanh với 1024 mẫu. Khi tôi đặt lấy mẫu đầu vào thành 24000 và lấy mẫu lại bộ đệm mẫu đầu vào thành 48000 trước khi mã hóa, tôi nhận được 1024 mẫu được lấy mẫu lại. Sau khi mã hóa 1024 tấm đệm này thành AAC, tôi nghe thấy âm thanh phù hợp trên đầu ra. Nhưng web-cam của tôi tạo ra 512 mẫu trong bộ đệm cho bất kỳ lấy mẫu đầu vào nào, khi tỷ lệ mẫu đầu ra phải là 48000 Hz. Vì vậy, tôi cần phải làm resampling trong mọi trường hợp, và tôi sẽ không có được chính xác 1024 mẫu trong bộ đệm sau khi resampling.
Có cách nào giải quyết vấn đề này trong chức năng ffmpeg-API không?
Tôi rất biết ơn sự giúp đỡ của bạn.
PS: Tôi đoán rằng tôi có thể tích lũy bộ đệm được lấy mẫu lại cho đến khi đếm mẫu trở thành 1024 và sau đó mã hóa nó, nhưng đây là luồng nên sẽ gặp sự cố với dấu thời gian và các thiết bị đầu vào khác. thích hợp.
Vấn đề hiện tại ra khỏi vấn đề mô tả trong [câu hỏi]: How to fill audio AVFrame (ffmpeg) with the data obtained from CMSampleBufferRef (AVFoundation)?
Đây là một mã với configs nghe codec (cũng là dòng video nhưng đoạn video làm việc tốt):
/*global variables*/
static AVFrame *aframe;
static AVFrame *frame;
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream *audio_st, *video_st;
Init()
{
AVCodec *audio_codec, *video_codec;
int ret;
avcodec_register_all();
av_register_all();
avformat_network_init();
avformat_alloc_output_context2(&oc, NULL, "flv", filename);
fmt = oc->oformat;
oc->oformat->video_codec = AV_CODEC_ID_H264;
oc->oformat->audio_codec = AV_CODEC_ID_AAC;
video_st = NULL;
audio_st = NULL;
if (fmt->video_codec != AV_CODEC_ID_NONE)
{ //… /*init video codec*/}
if (fmt->audio_codec != AV_CODEC_ID_NONE) {
audio_codec= avcodec_find_encoder(fmt->audio_codec);
if (!(audio_codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
avcodec_get_name(fmt->audio_codec));
exit(1);
}
audio_st= avformat_new_stream(oc, audio_codec);
if (!audio_st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
audio_st->id = oc->nb_streams-1;
//AAC:
audio_st->codec->sample_fmt = AV_SAMPLE_FMT_S16;
audio_st->codec->bit_rate = 32000;
audio_st->codec->sample_rate = 48000;
audio_st->codec->profile=FF_PROFILE_AAC_LOW;
audio_st->time_base = (AVRational){1, audio_st->codec->sample_rate };
audio_st->codec->channels = 1;
audio_st->codec->channel_layout = AV_CH_LAYOUT_MONO;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
audio_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (video_st)
{
// …
/*prepare video*/
}
if (audio_st)
{
aframe = avcodec_alloc_frame();
if (!aframe) {
fprintf(stderr, "Could not allocate audio frame\n");
exit(1);
}
AVCodecContext *c;
int ret;
c = audio_st->codec;
ret = avcodec_open2(c, audio_codec, 0);
if (ret < 0) {
fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
exit(1);
}
//…
}
và resampling và mã hóa âm thanh:
if (mType == kCMMediaType_Audio)
{
CMSampleTimingInfo timing_info;
CMSampleBufferGetSampleTimingInfo(sampleBuffer, 0, &timing_info);
double pts=0;
double dts=0;
AVCodecContext *c;
AVPacket pkt = { 0 }; // data and size must be 0;
int got_packet, ret;
av_init_packet(&pkt);
c = audio_st->codec;
CMItemCount numSamples = CMSampleBufferGetNumSamples(sampleBuffer);
NSUInteger channelIndex = 0;
CMBlockBufferRef audioBlockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
size_t audioBlockBufferOffset = (channelIndex * numSamples * sizeof(SInt16));
size_t lengthAtOffset = 0;
size_t totalLength = 0;
SInt16 *samples = NULL;
CMBlockBufferGetDataPointer(audioBlockBuffer, audioBlockBufferOffset, &lengthAtOffset, &totalLength, (char **)(&samples));
const AudioStreamBasicDescription *audioDescription = CMAudioFormatDescriptionGetStreamBasicDescription(CMSampleBufferGetFormatDescription(sampleBuffer));
SwrContext *swr = swr_alloc();
int in_smprt = (int)audioDescription->mSampleRate;
av_opt_set_int(swr, "in_channel_layout", AV_CH_LAYOUT_MONO, 0);
av_opt_set_int(swr, "out_channel_layout", audio_st->codec->channel_layout, 0);
av_opt_set_int(swr, "in_channel_count", audioDescription->mChannelsPerFrame, 0);
av_opt_set_int(swr, "out_channel_count", audio_st->codec->channels, 0);
av_opt_set_int(swr, "out_channel_layout", audio_st->codec->channel_layout, 0);
av_opt_set_int(swr, "in_sample_rate", audioDescription->mSampleRate,0);
av_opt_set_int(swr, "out_sample_rate", audio_st->codec->sample_rate,0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", audio_st->codec->sample_fmt, 0);
swr_init(swr);
uint8_t **input = NULL;
int src_linesize;
int in_samples = (int)numSamples;
ret = av_samples_alloc_array_and_samples(&input, &src_linesize, audioDescription->mChannelsPerFrame,
in_samples, AV_SAMPLE_FMT_S16P, 0);
*input=(uint8_t*)samples;
uint8_t *output=NULL;
int out_samples = av_rescale_rnd(swr_get_delay(swr, in_smprt) +in_samples, (int)audio_st->codec->sample_rate, in_smprt, AV_ROUND_UP);
av_samples_alloc(&output, NULL, audio_st->codec->channels, out_samples, audio_st->codec->sample_fmt, 0);
in_samples = (int)numSamples;
out_samples = swr_convert(swr, &output, out_samples, (const uint8_t **)input, in_samples);
aframe->nb_samples =(int) out_samples;
ret = avcodec_fill_audio_frame(aframe, audio_st->codec->channels, audio_st->codec->sample_fmt,
(uint8_t *)output,
(int) out_samples *
av_get_bytes_per_sample(audio_st->codec->sample_fmt) *
audio_st->codec->channels, 1);
aframe->channel_layout = audio_st->codec->channel_layout;
aframe->channels=audio_st->codec->channels;
aframe->sample_rate= audio_st->codec->sample_rate;
if (timing_info.presentationTimeStamp.timescale!=0)
pts=(double) timing_info.presentationTimeStamp.value/timing_info.presentationTimeStamp.timescale;
aframe->pts=pts*audio_st->time_base.den;
aframe->pts = av_rescale_q(aframe->pts, audio_st->time_base, audio_st->codec->time_base);
ret = avcodec_encode_audio2(c, &pkt, aframe, &got_packet);
if (ret < 0) {
fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
exit(1);
}
swr_free(&swr);
if (got_packet)
{
pkt.stream_index = audio_st->index;
pkt.pts = av_rescale_q(pkt.pts, audio_st->codec->time_base, audio_st->time_base);
pkt.dts = av_rescale_q(pkt.dts, audio_st->codec->time_base, audio_st->time_base);
// Write the compressed frame to the media file.
ret = av_interleaved_write_frame(oc, &pkt);
if (ret != 0) {
fprintf(stderr, "Error while writing audio frame: %s\n",
av_err2str(ret));
exit(1);
}
}
iPhone hỗ trợ hơn aac audio, chỉ tò mò tại sao bạn chỉ hỗ trợ AAC, không phải máy ảnh logitech hỗ trợ bất kỳ âm thanh nào sau đây, g711 (ulaw), apcm, mpeg2 vv. Hầu hết máy ảnh chúng tôi biết hỗ trợ ít nhất là g711, về mặt kỹ thuật với một số ami bổ sung cũng có thể. –
Codec AAC là một trong các codec bắt buộc trong nhiệm vụ của tôi và với các codec khác, tôi không gặp phải vấn đề gì. – Aleksei2414904
hi Aleksei2414904 i am mã hóa mẫu PCM thành android aac và phải đối mặt với cùng một vấn đề xin vui lòng giúp tôi nếu bạn tìm thấy bất kỳ giải pháp. –