Я пытаюсь записать аудио и видео с помощью микрофона и веб-камеры в файл mp4. Записанный файл можно воспроизвести, но со временем звук начинает отдаляться от видео, и в течение более длительного промежутка времени разрыв увеличивается. И аудио, и видео обрабатываются в отдельных потоках, для аудио я использую audiofifo, адаптированный из transcode_a cc. c пример https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/transcode_aac.c
Вот как я настраиваю потоки
Видео:
video_output_codec_ctx = video_stream->codec;
video_output_codec_ctx->bit_rate = 2000000;
video_output_codec_ctx->codec_id = AV_CODEC_ID_MPEG4;
video_output_codec_ctx->width = 640;
video_output_codec_ctx->height = 480;
video_stream->time_base = (AVRational){1, fps};
video_output_codec_ctx->time_base = video_stream->time_base;
video_output_codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
video_output_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
Аудио:
audio_output_codec_ctx->channels = OUTPUT_CHANNELS; // 2
audio_output_codec_ctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
audio_output_codec_ctx->sample_rate = audio_input_codec_ctx->sample_rate;
audio_output_codec_ctx->sample_fmt = audio_output_codec->sample_fmts[0];
audio_output_codec_ctx->bit_rate = OUTPUT_BIT_RATE; // 96000
audio_output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
/* Set the sample rate for the container. */
audio_stream->time_base.den = audio_input_codec_ctx->sample_rate;
audio_stream->time_base.num = 1;
Для видео, я увеличиваю индекс на 1 один раз кадр кодируется, и перед отправкой кадра в кодер я использую масштабирование, а также после получения кадра после этого пакеты записываются через av_interleaved_write_frame ().
output_frame->pts = av_rescale_q(video_frame_index, video_output_codec_ctx->time_base, video_input_format_ctx->streams[0]->time_base);
error = avcodec_send_frame(video_output_codec_ctx, output_frame);
error = avcodec_receive_packet(video_output_codec_ctx, &output_packet);
output_packet.stream_index = video_index;
output_packet.pts = av_rescale_q_rnd(output_packet.pts, video_input_format_ctx->streams[0]->time_base, output_format_context->streams[video_index]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
output_packet.dts = av_rescale_q_rnd(output_packet.dts, video_input_format_ctx->streams[0]->time_base, output_format_context->streams[video_index]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
output_packet.duration = ((output_format_context->streams[0]->time_base.den / output_format_context->streams[0]->time_base.num) / video_output_codec_ctx->time_base.den);
output_packet.pos = -1;
video_frame_index++;
Для аудио-точек я увеличиваю на frame-> nb_samples после того, как кадр закодирован, я использую масштабирование, после чего пакеты записываются через av_interleaved_write_frame ().
frame->pts = aud_pts;
aud_pts += frame->nb_samples;
error = avcodec_send_frame(audio_output_codec_ctx, frame);
error = avcodec_receive_packet(audio_output_codec_ctx, &output_packet);
output_packet.stream_index = audio_index;
output_packet.pts = av_rescale_q_rnd(output_packet.pts, audio_output_codec_ctx->time_base, output_format_context->streams[audio_index]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
output_packet.dts = av_rescale_q_rnd(output_packet.dts, audio_output_codec_ctx->time_base, output_format_context->streams[audio_index]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
output_packet.duration = av_rescale_q(output_packet.duration, audio_output_codec_ctx->time_base, output_format_context->streams[audio_index]->time_base);
Я новичок в FFmpeg C API, пробовал различные ресурсы / сообщения через inte rnet, но все еще не смог синхронизировать c аудио и видео в крепкий путь. Вот несколько вопросов, которые я хочу понять, которые помогут мне решить эту проблему. Любые мысли действительно ценятся по этому поводу.
Может ли FFmpeg C API обрабатывать syn c внутри или это то, что нужно обрабатывать со стороны вызывающего?
Правильно ли я настраиваю PTS для аудио и видео? Я заметил, что когда я использую fps ниже 20, я получаю Invalid pts (66667) <= last (66667) Операция не разрешена от кодера. Это должно быть что-то не так с тем, как я сейчас настраиваю видео PTS. Как я могу настроить видео PTS для обработки более низких кадров в секунду? </p>
Я также пытаюсь перенимать идею синхронизации часов c из учебника дранжера , не уверен, подойдет ли это для моего варианта использования, например где настроить аудио и видео часы, так как он использовал только декодеры, для аудио я использую fifo и не уверен, как настроить сэмплы на основе часов syn c, а также способ вызова и настройки refre sh таймер?
Есть ли лучший механизм для создания надежного syn c для моего случая использования, который может обрабатывать как аудио, так и видео, если они go не синхронизированы c, будет здорово иметь представление о сэмплах и настройке кадров на основе этого?