ffmpeg запись аудио в mp4
От: sergey2b ЮАР  
Дата: 19.07.23 04:13
Оценка:
используя avcodec я делаю рекордер который который записыват mp4 с видео и аудио
аудио я получаю в виде потока в формате AV_SAMPLE_FMT_FLTP

подскажите пожалуйста как сформировать AVFrame с аудио в формате AV_SAMPLE_FMT_FLTP
Re: ffmpeg запись аудио в mp4
От: DiPaolo Россия  
Дата: 19.07.23 04:22
Оценка: 9 (1)
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
Патриот здравого смысла
Re: ffmpeg запись аудио в mp4
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 19.07.23 04:26
Оценка: 9 (1)
Здравствуйте, sergey2b, Вы писали:

S>подскажите пожалуйста как сформировать AVFrame с аудио в формате AV_SAMPLE_FMT_FLTP


А в чём конкретно вопрос? Как правильно заполнить поля? Или как сконвертировать в формат? За конверсию отвечает libswresample отвечает.
Re[2]: ffmpeg запись аудио в mp4
От: sergey2b ЮАР  
Дата: 19.07.23 04:36
Оценка:
Здравствуйте, 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;
}

Re[3]: ffmpeg запись аудио в mp4
От: DiPaolo Россия  
Дата: 19.07.23 05:09
Оценка: 6 (1) +1
Без детального разбора в вашем коде, вот что нужно учесть:
— фрейм надо аллоцировать (почистить тоже не забыть)
— правильно посчитать sample_count
— полезно делать Дамп и открывать его в Audacity (или другой для работы с сырым аудио), чтобы удостовериться, что у тебя верные параметры количества каналов, сэмпл рейта, bits per sample и sample format; ВАЖНО не ошибись в функции записи дампа в файл!!!

Ну и посмотреть примеры от самого FFmpeg, на которые я давал ссылки выше. Их вполне достаточно, чтобы начать енкодить/декодить, муксировать/демуксировать и даже стримить. Вот еще до кучи https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/mux.c (посмотри функции работы с аудио).
Патриот здравого смысла
Отредактировано 19.07.2023 5:09 DiPaolo . Предыдущая версия .
Re[4]: ffmpeg запись аудио в mp4
От: sergey2b ЮАР  
Дата: 09.08.23 18:06
Оценка:
Здравствуйте, 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;

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.