Как заставить Media Source работать с timestampOffset ниже, чем appendWindowStart?
Я хочу использовать appendBuffer и добавлять только часть имеющейся у меня информации. Чтобы вырезать кусок с конца, я использую appendWindowEnd, и он работает. Чтобы вырезать его с самого начала, я должен установить timestampOffset ниже, чем appendWindowStart. Я видел, как shaka-player делает нечто подобное.
var appendWindowStart = Math.max(0, currentPeriod.startTime - windowFudge);
var appendWindowEnd = followingPeriod ? followingPeriod.startTime : duration;
...
var timestampOffset = currentPeriod.startTime -mediaState.stream.presentationTimeOffset;
Из моих тестов это работает, когда timestampOffset
- такой же как appendWindowStart
- На 1/10 секунды ниже
Не работает, когда timestampOffset ниже, чем это. Сегмент не добавляется. Это как-то связано с моими носителями или спецификация / реализация не позволяет этого?
Из веб-документов MDN:
Свойство appendWindowStart интерфейса SourceBuffer управляет отметкой времени начала окна добавления, диапазоном отметки времени, которую можно использовать для фильтрации того, какие мультимедийные данные добавляются в SourceBuffer. Будут добавлены кодированные медиакадры с временными метками в этом диапазоне, тогда как те, которые находятся за пределами этого диапазона, будут отфильтрованы.
Просто нашел это в спецификации, поэтому я обновляю вопрос:
Если временная метка представления меньше, чем appendWindowStart, установите для флага необходимой произвольной точки доступа значение true, отбросьте кодированный кадр и перейдите к началу цикла, чтобы начать обработку следующего кодированного кадра.
Некоторые реализации могут выбрать сбор некоторых из этих кодированных кадров с временной отметкой представления, меньшей, чем appendWindowStart, и использовать их для создания соединения в первом кодированном кадре, который имеет временную метку представления, большую или равную appendWindowStart, даже если этот кадр не является точкой произвольного доступа., Поддержка этого требует нескольких декодеров или быстрее, чем декодирование в реальном времени, так что пока это поведение не будет нормативным требованием.
Если отметка времени окончания кадра больше, чем appendWindowEnd, установите для флага необходимой произвольной точки доступа значение true, отбросьте кодированный кадр и перейдите к началу цикла, чтобы начать обработку следующего кодированного кадра.
Некоторые реализации могут выбрать сбор кодированных кадров с временной отметкой представления, меньшей, чем appendWindowEnd, и конечной временной отметкой кадра, большей, чем appendWindowEnd, и использовать их для создания склейки по части собранных кодированных кадров в окне добавления во время сбора и начальной части позже обрабатываются кадры, которые лишь частично перекрывают конец собранных кодированных кадров. Поддержка этого требует нескольких декодеров или быстрее, чем декодирование в реальном времени, так что пока это поведение не будет нормативным требованием. В связи со сбором закодированных кадров, которые охватывают appendWindowStart, реализации могут, таким образом, поддерживать бесщелевое объединение звука.
Если требуемый флаг точки произвольного доступа в буфере дорожки равен true, выполните следующие шаги: Если кодированный кадр не является точкой произвольного доступа, отбросьте кодированный кадр и перейдите к началу цикла, чтобы начать обработку следующего кодированного кадра., Установите флаг необходимости произвольной точки доступа в буфере дорожки на false.
а также
Точка произвольного доступа Позиция в медиа-сегменте, где декодирование и непрерывное воспроизведение могут начинаться без использования каких-либо предыдущих данных в сегменте. Для видео это, как правило, расположение I-кадров. В случае аудио большинство аудиокадров может рассматриваться как точка произвольного доступа. Поскольку видеотреки имеют тенденцию иметь более разреженное распределение точек произвольного доступа, местоположение этих точек обычно считается точками произвольного доступа для мультиплексированных потоков.
Означает ли это, что для видео мне нужно выбрать timeOffset, который попадает в кадр "I"?
1 ответ
Использование timestampOffset не требует I-кадра. Он просто сдвигает временную метку каждого кадра на это значение. Вычисления этого сдвига выполняются раньше всего (до того, как присоединится appendWindowStart)
Это использование appendWindowStart, которое влияет на ваши I-кадры.
appendWindowStart и appendWindowEnd действуют как AND над данными, которые вы добавляете.
MSE не обрабатывает ваши данные, устанавливая appendWindowStart, вы сообщаете исходному буферу, что любые данные, содержащиеся до этого времени, должны быть исключены. Также MSE работает на фундаментальном уровне GOP (группа изображений): от одного I-кадра до другой.
Итак, давайте представим эту группу изображений, состоящих из 16 кадров GOP, каждое из которых имеет длительность 1 с.
.IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP
Скажем, теперь вы установили appendWindowStart равным 10 В идеальном мире вы бы имели:
. PPPPPPP IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP
Все предыдущие 9 кадров со временем, предшествующим предшествующему appendWindowStart, были удалены.
Однако теперь эти P-кадры не могут быть декодированы, следовательно, MSE установил в спецификации "флаг необходимости произвольной точки доступа" в значение true, поэтому следующий кадр, добавленный в исходный буфер, может быть только I-кадром, и поэтому вы заканчиваете в исходном буфере с:
. IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP IPPPPPPPPPPPPPPP
Возможность добавить кадры между appendWindowStart и следующим I-кадром была бы невероятно трудной и дорогостоящей. Потребовалось бы декодировать все кадры перед добавлением их в исходный буфер, сохраняя их либо в виде необработанных данных YUV, либо, если аппаратное ускорение сохраняло изображение с поддержкой графического процессора.
Исходный буфер может содержать более минуты видео в любой момент времени. Представьте себе, если бы он имел дело с распакованными данными, а не со сжатыми данными.
Теперь, если мы хотим сохранить то же ограничение памяти, что и сейчас (которое составляет около 100 МБ максимум данных на исходный буфер), вам придется на лету перекомпрессировать содержимое перед добавлением его в исходный буфер.
не случится.