Я пытаюсь написать простой инструмент командной строки Windows Media Foundation для использования IMFSourceReader
и IMFSyncWriter
для загрузки видео, чтения видео и аудио в виде несжатых потоков и перекодирования их в H.246 /AAC с некоторыми жестко заданными настройками.
Простая программа Gist находится здесь
образец видео 1
образец видео 2
пример видео 3
(Примечание: видео, на которых я тестировал, все стерео, частота дискретизации 48000 КБ)
Программа работает, однако вВ некоторых случаях при сравнении вновь выведенного видео с оригиналом в программе редактирования я вижу, что скопированные видеопотоки совпадают, но аудиопоток копии предварительно фиксируется с некоторой тишиной, и звук смещается, что недопустимов моей ситуации.
audio samples:
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[silence] [silence] [silence] [audio1] [audio2] [audio3] ... etc
В подобных случаях первые поступающие видеокадры имеют ненулевую метку времени, но первые аудиокадры имеют 0 метку.
Я хотел бы иметь возможность создавать скопированное видео, у которого первый кадр из потоков видео и аудио равен 0, поэтому я сначала попытался вычесть эту начальную временную метку (videoOffset
) из всех последующих видеокадров, которые произвели видео, которое я хотел,но результатd в этой ситуации со звуком:
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[audio4] [audio5] [audio6] [audio7] [audio8] ... etc
Звуковая дорожка теперь немного смещена в другом направлении и все еще не выравнивается.Это также может иногда происходить, когда видеопоток имеет начальную временную метку 0 , но WMF все равно обрезает некоторые аудиосэмплы в начале (см. Пример видео 3)!
У меня естьбыл в состоянии исправить это синхронизирующее выравнивание и сместить видеопоток, чтобы начать с 0 со следующим кодом, вставленным в точке передачи данных аудиосэмпла в IMFSinkWriter
:
//inside read sample while loop
...
// LONGLONG llDuration has the currently read sample duration
// DWORD audioOffset has the global audio offset, starts as 0
// LONGLONG audioFrameTimestamp has the currently read sample timestamp
//add some random amount of silence in intervals of 1024 samples
static bool runOnce{ false };
if (!runOnce)
{
size_t numberOfSilenceBlocks = 1; //how to derive how many I need!? It's aribrary
size_t samples = 1024 * numberOfSilenceBlocks;
audioOffset = samples * 10000000 / audioSamplesPerSecond;
std::vector<uint8_t> silence(samples * audioChannels * bytesPerSample, 0);
WriteAudioBuffer(silence.data(), silence.size(), audioFrameTimeStamp, audioOffset);
runOnce= true;
}
LONGLONG audioTime = audioFrameTimeStamp + audioOffset;
WriteAudioBuffer(dataPtr, dataSize, audioTime, llDuration);
Как ни странно, это создаетвыходной видеофайл, который соответствует оригиналу.
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
Решением было вставить дополнительная тишина с размерами блоков 1024 в начале аудиопотока.Неважно, какие размеры аудиоблока предоставлены IMFSourceReader
, отступы кратны 1024.
Моя проблема в том, что, похоже, не обнаруживаетсяпричина молчания смещена.Зачем мне это нужно?Как я знаю, сколько мне нужно?После нескольких дней борьбы с этой проблемой я наткнулся на решение с блоком тишины 1024.
Некоторые видео, похоже, нуждаются только в 1 блоке заполнения, некоторые в 2 или более, а некоторые вообще не нуждаются в дополнительном заполнении!
Мой вопрос здесь:
Кто-нибудь знает, почему это происходит?
Не правильно ли я использую Media Foundation в этой ситуации, чтобы вызвать это?
Если я прав, как я могу использовать метаданные видео дляопределить, нужно ли мне заполнить аудиопоток и сколько в нем должно быть 1024 блоков молчания?
РЕДАКТИРОВАТЬ:
Дляпримеры видео выше:
образец видео 1 : видеопоток начинается с 0 и не требует дополнительных блоков , работает с исходными даннымив порядке.
пример видео 2 : поток видео начинается с 834166 (hns) и требуется 1 1024 блок молчания для синхронизации
образец видео 3 : видеопоток начинается с 0 и требуется 2 1024 блоков молчания для синхронизации.
ОБНОВЛЕНИЕ:
Другие вещи, которые я пробовал:
- Увеличение длительности первого видеокадра для учета смещения: Не дает эффекта.