У меня есть странная проблема в моем транскодере C/C++ FFmpeg, который принимает входной MP4 (различные входные кодеки) и производит и выводит MP4 (x264, базовая линия & AAC LC @ 44100 с помощью libfdk_aac):Перекодированный звук FFmpeg (AAC) останавливается после половины времени видео
В результате видео в mp4 имеет прекрасные изображения (x264), а звук (AAC LC) отлично работает, но воспроизводится только до половины видео.
Аудио не замедляется, не растягивается и не заикается. Он просто останавливается прямо в середине видео.
Один из намеков может заключаться в том, что входной файл имеет частоту дискретизации 22050 и 22050/44100 равен 0,5, но я действительно не понимаю, почему это приведет к простому остановке звука через половину времени. Я ожидаю, что такая ошибка приведет к неправильной скорости звука. Все работает отлично, если я не пытаюсь обеспечить соблюдение 44100 и вместо этого просто использовать входящий sample_rate.
Еще одна догадка заключается в том, что расчет очков не работает. Но звук звучит просто отлично (пока он не остановится), и я делаю точно то же самое для части видео, где она работает безупречно. «Точно», как в том же коде, но «audio» -переменные заменены на «видео» -переменные.
FFmpeg не сообщает об ошибках в течение всего процесса. Я также очищаю декодеры/кодировщики/interleaved_writing после того, как будет выполнено все считывание пакета с входа. Это хорошо работает для видео, поэтому я сомневаюсь, что в моем общем подходе есть много ошибок.
Вот функции моего кода (зачищенные от обработки ошибок & другого класса материал):
Настройка AudioCodecContext
outContext->_audioCodec = avcodec_find_encoder(outContext->_audioTargetCodecID);
outContext->_audioStream =
avformat_new_stream(outContext->_formatContext, outContext->_audioCodec);
outContext->_audioCodecContext = outContext->_audioStream->codec;
outContext->_audioCodecContext->channels = 2;
outContext->_audioCodecContext->channel_layout = av_get_default_channel_layout(2);
outContext->_audioCodecContext->sample_rate = 44100;
outContext->_audioCodecContext->sample_fmt = outContext->_audioCodec->sample_fmts[0];
outContext->_audioCodecContext->bit_rate = 128000;
outContext->_audioCodecContext->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
outContext->_audioCodecContext->time_base =
(AVRational){1, outContext->_audioCodecContext->sample_rate};
outContext->_audioStream->time_base = (AVRational){1, outContext->_audioCodecContext->sample_rate};
int retVal = avcodec_open2(outContext->_audioCodecContext, outContext->_audioCodec, NULL);
Resampler Настройка
outContext->_audioResamplerContext =
swr_alloc_set_opts(NULL, outContext->_audioCodecContext->channel_layout,
outContext->_audioCodecContext->sample_fmt,
outContext->_audioCodecContext->sample_rate,
_inputContext._audioCodecContext->channel_layout,
_inputContext._audioCodecContext->sample_fmt,
_inputContext._audioCodecContext->sample_rate,
0, NULL);
int retVal = swr_init(outContext->_audioResamplerContext);
Декодирование
decodedBytes = avcodec_decode_audio4( _inputContext._audioCodecContext,
_inputContext._audioTempFrame,
&p_gotAudioFrame, &_inputContext._currentPacket);
Преобразование (только если декодирование полученного кадра, конечно)
int retVal = swr_convert( outContext->_audioResamplerContext,
outContext->_audioConvertedFrame->data,
outContext->_audioConvertedFrame->nb_samples,
(const uint8_t**)_inputContext._audioTempFrame->data,
_inputContext._audioTempFrame->nb_samples);
Кодирование (только если декодирование производится кадр, конечно)
outContext->_audioConvertedFrame->pts =
av_frame_get_best_effort_timestamp(_inputContext._audioTempFrame);
// Init the new packet
av_init_packet(&outContext->_audioPacket);
outContext->_audioPacket.data = NULL;
outContext->_audioPacket.size = 0;
// Encode
int retVal = avcodec_encode_audio2(outContext->_audioCodecContext,
&outContext->_audioPacket,
outContext->_audioConvertedFrame,
&p_gotPacket);
// Set pts/dts time stamps for writing interleaved
av_packet_rescale_ts( &outContext->_audioPacket,
outContext->_audioCodecContext->time_base,
outContext->_audioStream->time_base);
outContext->_audioPacket.stream_index = outContext->_audioStream->index;
Письмо (только если кодирование составило пакет et, конечно)
int retVal = av_interleaved_write_frame(outContext->_formatContext, &outContext->_audioPacket);
Я совершенно не в курсе, что может привести к такому поведению.