зеркало из https://github.com/mozilla/gecko-dev.git
Bug 556821 - Use Ogg Skeleton presentation time for start of videos - r=cpearce
--HG-- extra : rebase_source : 83020ac5028e9f94cabe6a3c959cf84eeb25449f
This commit is contained in:
Родитель
60240d0fa2
Коммит
7ee1f56a07
|
@ -394,6 +394,7 @@ PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
|
|||
nsSkeletonState::nsSkeletonState(ogg_page* aBosPage)
|
||||
: nsOggCodecState(aBosPage),
|
||||
mVersion(0),
|
||||
mPresentationTime(0),
|
||||
mLength(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsSkeletonState);
|
||||
|
@ -407,7 +408,8 @@ nsSkeletonState::~nsSkeletonState()
|
|||
// Support for Ogg Skeleton 4.0, as per specification at:
|
||||
// http://wiki.xiph.org/Ogg_Skeleton_4
|
||||
|
||||
// Minimum length in bytes of a Skeleton 4.0 header packet.
|
||||
// Minimum length in bytes of a Skeleton header packet.
|
||||
#define SKELETON_MIN_HEADER_LEN 28
|
||||
#define SKELETON_4_0_MIN_HEADER_LEN 80
|
||||
|
||||
// Minimum length in bytes of a Skeleton 4.0 index packet.
|
||||
|
@ -421,6 +423,10 @@ nsSkeletonState::~nsSkeletonState()
|
|||
#define SKELETON_VERSION_MAJOR_OFFSET 8
|
||||
#define SKELETON_VERSION_MINOR_OFFSET 10
|
||||
|
||||
// Byte-offsets of the presentation time numerator and denominator
|
||||
#define SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET 12
|
||||
#define SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET 20
|
||||
|
||||
// Byte-offsets of the length of file field in the Skeleton 4.0 header packet.
|
||||
#define SKELETON_FILE_LENGTH_OFFSET 64
|
||||
|
||||
|
@ -434,7 +440,7 @@ nsSkeletonState::~nsSkeletonState()
|
|||
|
||||
static PRBool IsSkeletonBOS(ogg_packet* aPacket)
|
||||
{
|
||||
return aPacket->bytes >= SKELETON_4_0_MIN_HEADER_LEN &&
|
||||
return aPacket->bytes >= SKELETON_MIN_HEADER_LEN &&
|
||||
memcmp(reinterpret_cast<char*>(aPacket->packet), "fishead", 8) == 0;
|
||||
}
|
||||
|
||||
|
@ -699,6 +705,13 @@ PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
|
|||
if (IsSkeletonBOS(aPacket)) {
|
||||
PRUint16 verMajor = LEUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
|
||||
PRUint16 verMinor = LEUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);
|
||||
|
||||
// Read the presentation time. We read this before the version check as the
|
||||
// presentation time exists in all versions.
|
||||
PRInt64 n = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
|
||||
PRInt64 d = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
|
||||
mPresentationTime = d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * 1000;
|
||||
|
||||
mVersion = SKELETON_VERSION(verMajor, verMinor);
|
||||
if (mVersion < SKELETON_VERSION(4,0) ||
|
||||
mVersion >= SKELETON_VERSION(5,0) ||
|
||||
|
|
|
@ -214,6 +214,9 @@ public:
|
|||
virtual PRInt64 Time(PRInt64 granulepos) { return -1; }
|
||||
virtual PRBool Init() { return PR_TRUE; }
|
||||
|
||||
// Return PR_TRUE if the given time (in milliseconds) is within
|
||||
// the presentation time defined in the skeleton track.
|
||||
PRBool IsPresentable(PRInt64 aTime) { return aTime >= mPresentationTime; }
|
||||
|
||||
// Stores the offset of the page on which a keyframe starts,
|
||||
// and its presentation time.
|
||||
|
@ -283,6 +286,9 @@ private:
|
|||
// Version of the decoded skeleton track, as per the SKELETON_VERSION macro.
|
||||
PRUint32 mVersion;
|
||||
|
||||
// Presentation time of the resource in milliseconds
|
||||
PRInt64 mPresentationTime;
|
||||
|
||||
// Length of the resource in bytes.
|
||||
PRInt64 mLength;
|
||||
|
||||
|
|
|
@ -628,7 +628,7 @@ PRBool nsOggReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
// packets we read subsequently.
|
||||
mTheoraGranulepos = packet.granulepos;
|
||||
}
|
||||
|
||||
|
||||
if (DecodeTheora(frames, &packet) == NS_ERROR_OUT_OF_MEMORY) {
|
||||
NS_WARNING("Theora decode memory allocation failure!");
|
||||
return PR_FALSE;
|
||||
|
@ -741,6 +741,7 @@ PRBool nsOggReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
|
||||
PRInt64 time = mTheoraState->StartTime(mTheoraGranulepos);
|
||||
NS_ASSERTION(packet.granulepos != -1, "Must know packet granulepos");
|
||||
|
||||
if (!aKeyframeSkip ||
|
||||
(th_packet_iskeyframe(&packet) == 1 && time >= aTimeThreshold))
|
||||
{
|
||||
|
@ -754,13 +755,17 @@ PRBool nsOggReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
|||
// Push decoded data into the video frame queue.
|
||||
for (PRUint32 i = 0; i < frames.Length(); i++) {
|
||||
nsAutoPtr<VideoData> data(frames[i].forget());
|
||||
if (aKeyframeSkip && data->mKeyframe) {
|
||||
aKeyframeSkip = PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aKeyframeSkip && data->mEndTime >= aTimeThreshold) {
|
||||
mVideoQueue.Push(data.forget());
|
||||
decoded++;
|
||||
// Don't use the frame if it's outside the bounds of the presentation
|
||||
// start time in the skeleton track.
|
||||
if (!mSkeletonState || mSkeletonState->IsPresentable(data->mTime)) {
|
||||
if (aKeyframeSkip && data->mKeyframe) {
|
||||
aKeyframeSkip = PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aKeyframeSkip && data->mEndTime >= aTimeThreshold) {
|
||||
mVideoQueue.Push(data.forget());
|
||||
decoded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,6 +201,7 @@ _TEST_FILES += \
|
|||
bug523816.ogv \
|
||||
bug533822.ogg \
|
||||
bug557094.ogv \
|
||||
bug556821.ogv \
|
||||
bug580982.webm \
|
||||
bug603918.webm \
|
||||
bug604067.webm \
|
||||
|
|
Двоичный файл не отображается.
|
@ -74,6 +74,8 @@ var gPlayTests = [
|
|||
{ name:"bug504613.ogv", type:"video/ogg", duration:Number.NaN },
|
||||
// Multiple audio streams.
|
||||
{ name:"bug516323.ogv", type:"video/ogg", duration:4.208 },
|
||||
// oggz-chop with non-keyframe as first frame
|
||||
{ name:"bug556821.ogv", type:"video/ogg", duration:2.551 },
|
||||
|
||||
// Encoded with vorbis beta1, includes unusually sized codebooks
|
||||
{ name:"beta-phrasebook.ogg", type:"audio/ogg", duration:4.01 },
|
||||
|
|
Загрузка…
Ссылка в новой задаче