используя avcodec я делаю рекордер который который записыват mp4 с видео и аудио
аудио я получаю в виде потока в формате AV_SAMPLE_FMT_FLTP
подскажите пожалуйста как сформировать AVFrame с аудио в формате AV_SAMPLE_FMT_FLTP
S>используя avcodec я делаю рекордер который который записыват mp4 с видео и аудио
S>аудио я получаю в виде потока в формате AV_SAMPLE_FMT_FLTP
S>подскажите пожалуйста как сформировать AVFrame с аудио в формате AV_SAMPLE_FMT_FLTP
Непонятно, в чем конкретно сложность и вопрос. Подкину пару примеров:
— вот пример аудио транскодинга
https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/transcode_aac.c (смотри функцию convert_samples())
— вот енкодирование аудио с заданием сэмпл формата
https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/encode_audio.c
Здравствуйте, Nuzhny, Вы писали:
N>А в чём конкретно вопрос? Как правильно заполнить поля? Или как сконвертировать в формат? За конверсию отвечает libswresample отвечает.
как заполнить поля
это моя первая попытка
я пока в качестве теста использую аудио полученное из mp4 (если я беру AVFrame считыванный из mp4 и передаю его на запись то все записываеться отлично те процесс считывания и записи работает)
затем я пытаюсь взять массив float и сформировать AVFrame и это уже не работает
конечная цель записывать поток с микрофона
int process_audio(AVFrame *avframe)
{
int unpadded_linesize = avframe->nb_samples * av_get_bytes_per_sample((AVSampleFormat)avframe->format);
// fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file);
AVFrame *frame = av_frame_alloc();
//int sample_size = _bit_per_sample / 8 * _channel_num;
int sample_size = unpadded_linesize;
uint8_t* data = avframe->extended_data[0];
//uint8_t* data = avframe->data[0];
int sample_count = avframe->nb_samples;
int _fmt = avframe->format;
int _sample_rate = avframe->sample_rate;
int _channel_num = avframe->channels;
//wasapi time unit is 100ns,so time base is NS_PER_SEC
//frame->pts = _use_device_ts ? device_ts * 100 : av_gettime_relative();
frame->pts = avframe->pts;
// 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, &unpadded_linesize, data, _channel_num, sample_count, (enum AVSampleFormat)_fmt, 1);
encode.setAudioFrame(frame);
av_frame_free(&frame);
return 0;
}
Без детального разбора в вашем коде, вот что нужно учесть:
— фрейм надо аллоцировать (почистить тоже не забыть)
— правильно посчитать sample_count
— полезно делать Дамп и открывать его в Audacity (или другой для работы с сырым аудио), чтобы удостовериться, что у тебя верные параметры количества каналов, сэмпл рейта, bits per sample и sample format; ВАЖНО не ошибись в функции записи дампа в файл!!!
Ну и посмотреть примеры от самого FFmpeg, на которые я давал ссылки выше. Их вполне достаточно, чтобы начать енкодить/декодить, муксировать/демуксировать и даже стримить. Вот еще до кучи
https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/mux.c (посмотри функции работы с аудио).
Здравствуйте, DiPaolo, Вы писали:
это рабочий прототип который позволяет записывать audio from NDI stream
int nb_samples = audio_frame.no_samples;
int channels = audio_frame.no_channels;
int sample_rate = audio_frame.sample_rate;
int outputBufferLen = nb_samples * channels * 2; //nb_samples & channels * 2;
short* outputBuffer = new short[outputBufferLen]; //outputBufferLen/2
for (int i = 0; i < nb_samples; i++)
{
for (int c = 0; c < channels; c++)
{
float* extended_data = (float*)((uint8_t*)audio_frame.p_data + c * audio_frame.channel_stride_in_bytes);
float sample = extended_data[i];
if (sample < -1.0f) sample = -1.0f;
else if (sample > 1.0f) sample = 1.0f;
outputBuffer[i * channels + c] = (short)round(sample * 32767.0f);
}
}
const int max_buffer_size = av_samples_get_buffer_size(NULL, channels, nb_samples, AV_SAMPLE_FMT_S16, 1);
AVFrame* frame = av_frame_alloc();
assert(frame);
// set frame parameters
frame->nb_samples = nb_samples;
frame->format = AV_SAMPLE_FMT_S16;
frame->sample_rate = sample_rate; //sample_rate;
frame->channel_layout = AV_CH_LAYOUT_STEREO; //decoded_frame->channel_layout;//AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT;
frame->channels = channels;
AVRational audio_time_base = encoder.video_time_base();
frame->pts = av_rescale_q(audio_frame.timecode, NDI_TIME_BASE_Q, audio_time_base);
frame->duration = av_rescale_q(1, (AVRational){audio_frame.no_samples, audio_frame.sample_rate}, audio_time_base);
// allocate frame buffers
if (av_frame_get_buffer(frame, 32) < 0) {
printf("av_frame_get_buffer()\n");
exit(0);
}
assert(frame->data[0]);
assert(frame->linesize[0] == max_buffer_size);
memset(frame->data[0], 0, max_buffer_size);
memmove(frame->data[0], outputBuffer, outputBufferLen);
encoder.setAudioFrame(frame);
av_frame_free(&frame);
delete [] outputBuffer;