Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
brainfood
/
videojs-contrib-hls
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
ced9b85e
authored
2013-10-23 11:49:41 -0400
by
Tom Johnson
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Merge branch 'master' of
https://bithub.brightcove.com/tojohnson/video-js-hls
2 parents
0f3916fb
5351582b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
232 additions
and
105 deletions
example.html
src/exp-golomb.js
src/flv-tag.js
src/h264-stream.js
test/exp-golomb_test.js
test/video-js-hls.html
test/video-js-hls_test.js
example.html
View file @
ced9b85
/
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
...
...
src/exp-golomb.js
View file @
ced9b85
(
function
(
window
)
{
/**
* Parser for exponential Golomb codes, a variable-bitwidth number encoding
* scheme used by h264.
*/
window
.
videojs
.
hls
.
ExpGolomb
=
function
(
workingData
)
{
var
// the number of bytes left to examine in workingData
workingBytesAvailable
=
workingData
.
byteLength
,
// the current word being examined
workingWord
,
// :uint
workingWord
=
0
,
// :uint
// the number of bits left to examine in the current word
workingBitsAvailable
;
// :uint;
workingBitsAvailable
=
0
;
// :uint;
// ():uint
this
.
length
=
function
()
{
...
...
@@ -21,15 +25,24 @@ window.videojs.hls.ExpGolomb = function(workingData) {
return
(
8
*
workingBytesAvailable
)
+
workingBitsAvailable
;
};
this
.
logStuff
=
function
()
{
console
.
log
(
'bits'
,
workingBitsAvailable
,
'word'
,
(
workingWord
>>>
0
));
};
// ():void
this
.
loadWord
=
function
()
{
var
position
=
workingData
.
byteLength
-
workingBytesAvailable
,
workingBytes
=
new
Uint8Array
(
4
),
availableBytes
=
Math
.
min
(
4
,
workingBytesAvailable
);
// console.assert(availableBytes > 0);
if
(
availableBytes
===
0
)
{
throw
new
Error
(
'no bytes available'
);
}
workingBytes
.
set
(
workingData
.
subarray
(
0
,
availableBytes
));
workingBytes
.
set
(
workingData
.
subarray
(
position
,
position
+
availableBytes
));
workingWord
=
new
DataView
(
workingBytes
.
buffer
).
getUint32
(
0
);
// track the amount of workingData that has been processed
...
...
@@ -37,23 +50,23 @@ window.videojs.hls.ExpGolomb = function(workingData) {
workingBytesAvailable
-=
availableBytes
;
};
// (
size
:int):void
this
.
skipBits
=
function
(
size
)
{
// (
count
:int):void
this
.
skipBits
=
function
(
count
)
{
var
skipBytes
;
// :int
if
(
workingBitsAvailable
>
size
)
{
workingWord
<<=
size
;
workingBitsAvailable
-=
size
;
if
(
workingBitsAvailable
>
count
)
{
workingWord
<<=
count
;
workingBitsAvailable
-=
count
;
}
else
{
size
-=
workingBitsAvailable
;
skipBytes
=
size
/
8
;
count
-=
workingBitsAvailable
;
skipBytes
=
count
/
8
;
size
-=
(
skipBytes
*
8
);
working
Data
.
position
+
=
skipBytes
;
count
-=
(
skipBytes
*
8
);
working
BytesAvailable
-
=
skipBytes
;
this
.
loadWord
();
workingWord
<<=
size
;
workingBitsAvailable
-=
size
;
workingWord
<<=
count
;
workingBitsAvailable
-=
count
;
}
};
...
...
@@ -63,17 +76,17 @@ window.videojs.hls.ExpGolomb = function(workingData) {
bits
=
Math
.
min
(
workingBitsAvailable
,
size
),
// :uint
valu
=
workingWord
>>>
(
32
-
bits
);
// :uint
console
.
assert
(
32
>
size
,
'Cannot read more than 32 bits at a time'
);
console
.
assert
(
size
<
32
,
'Cannot read more than 32 bits at a time'
);
workingBitsAvailable
-=
bits
;
if
(
0
<
workingBitsAvailable
)
{
if
(
workingBitsAvailable
>
0
)
{
workingWord
<<=
bits
;
}
else
{
}
else
if
(
workingBytesAvailable
>
0
)
{
this
.
loadWord
();
}
bits
=
size
-
bits
;
if
(
0
<
bits
)
{
if
(
bits
>
0
)
{
return
valu
<<
bits
|
this
.
readBits
(
bits
);
}
else
{
return
valu
;
...
...
@@ -82,18 +95,19 @@ window.videojs.hls.ExpGolomb = function(workingData) {
// ():uint
this
.
skipLeadingZeros
=
function
()
{
var
clz
;
// :uint
for
(
clz
=
0
;
clz
<
workingBitsAvailable
;
++
clz
)
{
if
(
0
!==
(
workingWord
&
(
0x80000000
>>>
clz
)))
{
workingWord
<<=
clz
;
workingBitsAvailable
-=
clz
;
return
clz
;
var
leadingZeroCount
;
// :uint
for
(
leadingZeroCount
=
0
;
leadingZeroCount
<
workingBitsAvailable
;
++
leadingZeroCount
)
{
if
(
0
!==
(
workingWord
&
(
0x80000000
>>>
leadingZeroCount
)))
{
// the first bit of working word is 1
workingWord
<<=
leadingZeroCount
;
workingBitsAvailable
-=
leadingZeroCount
;
return
leadingZeroCount
;
}
}
// we exhausted workingWord and still have not found a 1
this
.
loadWord
();
return
clz
+
this
.
skipLeadingZeros
();
this
.
loadWord
();
return
leadingZeroCount
+
this
.
skipLeadingZeros
();
};
// ():void
...
...
src/flv-tag.js
View file @
ced9b85
...
...
@@ -105,7 +105,8 @@ hls.FlvTag = function(type, extraData) {
// Rewind to the marker and write the size
if
(
this
.
length
===
adHoc
+
4
)
{
this
.
length
-=
4
;
// we started a nal unit, but didnt write one, so roll back the 4 byte size value
// we started a nal unit, but didnt write one, so roll back the 4 byte size value
this
.
length
-=
4
;
}
else
if
(
adHoc
>
0
)
{
nalStart
=
adHoc
+
4
;
nalLength
=
this
.
length
-
nalStart
;
...
...
@@ -207,13 +208,16 @@ hls.FlvTag = function(type, extraData) {
len
=
this
.
length
-
11
;
// write the DataSize field
this
.
bytes
[
1
]
=
(
len
&
0x00FF0000
)
>>>
16
;
this
.
bytes
[
2
]
=
(
len
&
0x0000FF00
)
>>>
8
;
this
.
bytes
[
3
]
=
(
len
&
0x000000FF
)
>>>
0
;
// write the Timestamp
this
.
bytes
[
4
]
=
(
this
.
pts
&
0x00FF0000
)
>>>
16
;
this
.
bytes
[
5
]
=
(
this
.
pts
&
0x0000FF00
)
>>>
8
;
this
.
bytes
[
6
]
=
(
this
.
pts
&
0x000000FF
)
>>>
0
;
this
.
bytes
[
7
]
=
(
this
.
pts
&
0xFF000000
)
>>>
24
;
// write the StreamID
this
.
bytes
[
8
]
=
0
;
this
.
bytes
[
9
]
=
0
;
this
.
bytes
[
10
]
=
0
;
...
...
@@ -230,9 +234,9 @@ hls.FlvTag = function(type, extraData) {
};
};
hls
.
FlvTag
.
AUDIO_TAG
=
0x08
;
// :uint
hls
.
FlvTag
.
VIDEO_TAG
=
0x09
;
// :uint
hls
.
FlvTag
.
METADATA_TAG
=
0x12
;
// :uint
hls
.
FlvTag
.
AUDIO_TAG
=
0x08
;
//
== 8,
:uint
hls
.
FlvTag
.
VIDEO_TAG
=
0x09
;
//
== 9,
:uint
hls
.
FlvTag
.
METADATA_TAG
=
0x12
;
//
== 18,
:uint
// (tag:ByteArray):Boolean {
hls
.
FlvTag
.
isAudioFrame
=
function
(
tag
)
{
...
...
src/h264-stream.js
View file @
ced9b85
...
...
@@ -55,6 +55,19 @@
}
};
/**
* NAL unit
* |- NAL header -|------ RBSP ------|
*
* NAL unit: Network abstraction layer unit. The combination of a NAL
* header and an RBSP.
* NAL header: the encapsulation unit for transport-specific metadata in
* an h264 stream.
* RBSP: raw bit-stream payload. The actual encoded video data.
*
* SPS: sequence parameter set. Part of the RBSP. Metadata to be applied
* to a complete video sequence, like width and height.
*/
this
.
getSps0Rbsp
=
function
()
{
// :ByteArray
// remove emulation bytes. Is this nesessary? is there ever emulation
// bytes in the SPS?
...
...
@@ -62,22 +75,20 @@
spsCount
=
0
,
sps0
=
this
.
sps
[
0
],
// :ByteArray
rbspCount
=
0
,
s
,
// :uint
e
,
// :uint
rbsp
,
// :ByteArray
o
;
// :uint
s
=
1
;
e
=
sps0
.
byteLength
-
2
;
rbsp
=
new
Uint8Array
(
sps0
.
byteLength
);
// new ByteArray();
for
(
o
=
s
;
o
<
e
;)
{
if
(
3
!==
sps0
[
o
+
2
])
{
o
+=
3
;
}
else
if
(
0
!==
sps0
[
o
+
1
])
{
o
+=
2
;
}
else
if
(
0
!==
sps0
[
o
+
0
])
{
o
+=
1
;
start
=
1
,
// :uint
end
=
sps0
.
byteLength
-
2
,
// :uint
rbsp
=
new
Uint8Array
(
sps0
.
byteLength
),
// :ByteArray
offset
=
0
;
// :uint
// H264 requires emulation bytes (0x03) be dropped to interpret NAL
// units. For instance, 0x8a03b4 should be read as 0x8ab4.
for
(
offset
=
start
;
offset
<
end
;)
{
if
(
3
!==
sps0
[
offset
+
2
])
{
offset
+=
3
;
}
else
if
(
0
!==
sps0
[
offset
+
1
])
{
offset
+=
2
;
}
else
if
(
0
!==
sps0
[
offset
+
0
])
{
offset
+=
1
;
}
else
{
console
.
log
(
'found emulation bytes'
);
...
...
@@ -85,21 +96,22 @@
spsCount
+=
2
;
rbspCount
+=
2
;
if
(
o
>
s
)
{
if
(
o
ffset
>
start
)
{
// If there are bytes to write, write them
rbsp
.
set
(
sps0
.
subarray
(
0
,
o
-
s
),
rbspCount
);
spsCount
+=
o
-
s
;
rbspCount
+=
o
-
s
;
rbsp
.
set
(
sps0
.
subarray
(
start
,
offset
-
start
),
rbspCount
);
spsCount
+=
o
ffset
-
start
;
rbspCount
+=
o
ffset
-
start
;
}
// skip the emulation bytes
o
+=
3
;
s
=
o
;
o
ffset
+=
3
;
s
tart
=
offset
;
}
}
// copy any remaining bytes
rbsp
.
set
(
sps0
.
subarray
(
spsCount
),
rbspCount
);
// sps0.readBytes(rbsp, rbsp.length);
return
rbsp
;
};
...
...
@@ -122,10 +134,10 @@
frame_mbs_only_flag
,
// :int
frame_cropping_flag
,
// :Boolean
frame_crop_left_offset
,
// :int
frame_crop_right_offset
,
// :int
frame_crop_top_offset
,
// :int
frame_crop_bottom_offset
,
// :int
frame_crop_left_offset
=
0
,
// :int
frame_crop_right_offset
=
0
,
// :int
frame_crop_top_offset
=
0
,
// :int
frame_crop_bottom_offset
=
0
,
// :int
width
,
height
;
...
...
@@ -202,8 +214,8 @@
frame_crop_bottom_offset
=
expGolomb
.
readUnsignedExpGolomb
();
}
width
=
((
pic_width_in_mbs_minus1
+
1
)
*
16
)
-
frame_crop_left_offset
*
2
-
frame_crop_right_offset
*
2
;
height
=
((
2
-
frame_mbs_only_flag
)
*
(
pic_height_in_map_units_minus1
+
1
)
*
16
)
-
(
frame_crop_top_offset
*
2
)
-
(
frame_crop_bottom_offset
*
2
);
width
=
((
pic_width_in_mbs_minus1
+
1
)
*
16
)
-
frame_crop_left_offset
*
2
-
frame_crop_right_offset
*
2
;
height
=
((
2
-
frame_mbs_only_flag
)
*
(
pic_height_in_map_units_minus1
+
1
)
*
16
)
-
(
frame_crop_top_offset
*
2
)
-
(
frame_crop_bottom_offset
*
2
);
tag
.
writeMetaDataDouble
(
"videocodecid"
,
7
);
tag
.
writeMetaDataDouble
(
"width"
,
width
);
...
...
@@ -318,20 +330,25 @@
};
// (data:ByteArray, o:int, l:int):void
this
.
writeBytes
=
function
(
data
,
o
,
l
)
{
this
.
writeBytes
=
function
(
data
,
o
ffset
,
length
)
{
var
nalUnitSize
,
// :uint
s
,
// :uint
e
,
// :uint
s
tart
,
// :uint
e
nd
,
// :uint
t
;
// :int
if
(
l
<=
0
)
{
// default argument values
offset
=
offset
||
0
;
length
=
length
||
0
;
if
(
length
<=
0
)
{
// data is empty so there's nothing to write
return
;
}
// scan through the bytes until we find the start code (0x000001) for a
// NAL unit and then begin writing it out
// strip NAL start codes as we go
switch
(
state
)
{
default
:
/* falls through */
...
...
@@ -341,11 +358,11 @@
case
1
:
// A NAL unit may be split across two TS packets. Look back a bit to
// make sure the prefix of the start code wasn't already written out.
if
(
data
[
o
]
<=
1
)
{
if
(
data
[
o
ffset
]
<=
1
)
{
nalUnitSize
=
h264Frame
?
h264Frame
.
nalUnitSize
()
:
0
;
if
(
nalUnitSize
>=
1
&&
h264Frame
.
negIndex
(
1
)
===
0
)
{
// ?? ?? 00 | O[01] ?? ??
if
(
1
===
data
[
o
]
&&
2
<=
nalUnitSize
&&
0
===
h264Frame
.
negIndex
(
2
))
{
if
(
1
===
data
[
o
ffset
]
&&
2
<=
nalUnitSize
&&
0
===
h264Frame
.
negIndex
(
2
))
{
// ?? 00 00 : 01
if
(
3
<=
nalUnitSize
&&
0
===
h264Frame
.
negIndex
(
3
))
{
h264Frame
.
length
-=
3
;
// 00 00 00 : 01
...
...
@@ -354,10 +371,10 @@
}
state
=
3
;
return
this
.
writeBytes
(
data
,
o
+
1
,
l
-
1
);
return
this
.
writeBytes
(
data
,
o
ffset
+
1
,
length
-
1
);
}
if
(
1
<
l
&&
0
===
data
[
o
]
&&
1
===
data
[
o
+
1
])
{
if
(
1
<
l
ength
&&
0
===
data
[
offset
]
&&
1
===
data
[
offset
+
1
])
{
// ?? 00 | 00 01
if
(
2
<=
nalUnitSize
&&
0
===
h264Frame
.
negIndex
(
2
))
{
h264Frame
.
length
-=
2
;
// 00 00 : 00 01
...
...
@@ -366,14 +383,17 @@
}
state
=
3
;
return
this
.
writeBytes
(
data
,
o
+
2
,
l
-
2
);
return
this
.
writeBytes
(
data
,
o
ffset
+
2
,
length
-
2
);
}
if
(
2
<
l
&&
0
===
data
[
o
]
&&
0
===
data
[
o
+
1
]
&&
1
===
data
[
o
+
2
])
{
if
(
2
<
length
&&
0
===
data
[
offset
]
&&
0
===
data
[
offset
+
1
]
&&
1
===
data
[
offset
+
2
])
{
// 00 | 00 00 01
h264Frame
.
length
-=
1
;
state
=
3
;
return
this
.
writeBytes
(
data
,
o
+
3
,
l
-
3
);
return
this
.
writeBytes
(
data
,
o
ffset
+
3
,
length
-
3
);
}
}
}
...
...
@@ -382,45 +402,45 @@
state
=
2
;
/* falls through */
case
2
:
// Look for start codes in data
s
=
o
;
// s = Start
e
=
s
+
l
;
// e = End
for
(
t
=
e
-
3
;
o
<
t
;)
{
if
(
1
<
data
[
o
+
2
])
{
o
+=
3
;
// if data[o + 2] is greater than 1, there is no way a start code can begin before o
+3
}
else
if
(
0
!==
data
[
o
+
1
])
{
o
+=
2
;
}
else
if
(
0
!==
data
[
o
])
{
o
+=
1
;
s
tart
=
offset
;
e
nd
=
start
+
length
;
for
(
t
=
e
nd
-
3
;
offset
<
t
;)
{
if
(
1
<
data
[
o
ffset
+
2
])
{
o
ffset
+=
3
;
// if data[offset + 2] is greater than 1, there is no way a start code can begin before offset
+3
}
else
if
(
0
!==
data
[
o
ffset
+
1
])
{
o
ffset
+=
2
;
}
else
if
(
0
!==
data
[
o
ffset
])
{
o
ffset
+=
1
;
}
else
{
// If we get here we have 00 00 00 or 00 00 01
if
(
1
===
data
[
o
+
2
])
{
if
(
o
>
s
)
{
h264Frame
.
writeBytes
(
data
,
s
,
o
-
s
);
if
(
1
===
data
[
o
ffset
+
2
])
{
if
(
o
ffset
>
start
)
{
h264Frame
.
writeBytes
(
data
,
s
tart
,
offset
-
start
);
}
state
=
3
;
o
+=
3
;
return
this
.
writeBytes
(
data
,
o
,
e
-
o
);
o
ffset
+=
3
;
return
this
.
writeBytes
(
data
,
o
ffset
,
end
-
offset
);
}
if
(
e
-
o
>=
4
&&
0
===
data
[
o
+
2
]
&&
1
===
data
[
o
+
3
])
{
if
(
o
>
s
)
{
h264Frame
.
writeBytes
(
data
,
s
,
o
-
s
);
if
(
e
nd
-
offset
>=
4
&&
0
===
data
[
offset
+
2
]
&&
1
===
data
[
offset
+
3
])
{
if
(
o
ffset
>
start
)
{
h264Frame
.
writeBytes
(
data
,
s
tart
,
offset
-
start
);
}
state
=
3
;
o
+=
4
;
return
this
.
writeBytes
(
data
,
o
,
e
-
o
);
o
ffset
+=
4
;
return
this
.
writeBytes
(
data
,
o
ffset
,
end
-
offset
);
}
// We are at the end of the buffer, or we have 3 NULLS followed by
// something that is not a 1, either way we can step forward by at
// least 3
o
+=
3
;
o
ffset
+=
3
;
}
}
// We did not find any start codes. Try again next packet
state
=
1
;
h264Frame
.
writeBytes
(
data
,
s
,
l
);
h264Frame
.
writeBytes
(
data
,
s
tart
,
length
);
return
;
case
3
:
// The next byte is the first byte of a NAL Unit
...
...
@@ -447,7 +467,7 @@
}
// setup to begin processing the new NAL unit
nalUnitType
=
data
[
o
]
&
0x1F
;
nalUnitType
=
data
[
o
ffset
]
&
0x1F
;
if
(
h264Frame
&&
9
===
nalUnitType
)
{
this
.
finishFrame
();
// We are starting a new access unit. Flush the previous one
}
...
...
@@ -461,7 +481,7 @@
h264Frame
.
startNalUnit
();
state
=
2
;
// We know there will not be an overlapping start code, so we can skip that test
return
this
.
writeBytes
(
data
,
o
,
l
);
return
this
.
writeBytes
(
data
,
o
ffset
,
length
);
/*--------------------------------------------------------------------------------------------------------------------*/
}
// switch
};
...
...
test/exp-golomb_test.js
0 → 100644
View file @
ced9b85
(
function
(
window
)
{
/*
======== A Handy Little QUnit Reference ========
http://api.qunitjs.com/
Test methods:
module(name, {[setup][ ,teardown]})
test(name, callback)
expect(numberOfAssertions)
stop(increment)
start(decrement)
Test assertions:
ok(value, [message])
equal(actual, expected, [message])
notEqual(actual, expected, [message])
deepEqual(actual, expected, [message])
notDeepEqual(actual, expected, [message])
strictEqual(actual, expected, [message])
notStrictEqual(actual, expected, [message])
throws(block, [expected], [message])
*/
var
buffer
,
expGolomb
,
view
;
module
(
'Exponential Golomb coding'
);
test
(
'small numbers are coded correctly'
,
function
()
{
var
expected
=
[
[
0xF8
,
0
],
[
0x5F
,
1
],
[
0x7F
,
2
],
[
0x27
,
3
],
[
0x2F
,
4
],
[
0x37
,
5
],
[
0x3F
,
6
],
[
0x11
,
7
],
[
0x13
,
8
],
[
0x15
,
9
]
],
i
=
expected
.
length
,
result
;
while
(
i
--
)
{
buffer
=
new
Uint8Array
([
expected
[
i
][
0
]]);
expGolomb
=
new
window
.
videojs
.
hls
.
ExpGolomb
(
buffer
);
result
=
expGolomb
.
readUnsignedExpGolomb
();
equal
(
expected
[
i
][
1
],
result
,
expected
[
i
][
0
]
+
' is decoded to '
+
expected
[
i
][
1
]);
}
});
test
(
'drops working data as it is parsed'
,
function
()
{
var
expGolomb
=
new
window
.
videojs
.
hls
.
ExpGolomb
(
new
Uint8Array
([
0x00
,
0xFF
]));
expGolomb
.
skipBits
(
8
);
equal
(
8
,
expGolomb
.
bitsAvailable
(),
'8 bits remain'
);
equal
(
0xFF
,
expGolomb
.
readBits
(
8
),
'the second byte is read'
);
});
test
(
'drops working data when skipping leading zeros'
,
function
()
{
var
expGolomb
=
new
window
.
videojs
.
hls
.
ExpGolomb
(
new
Uint8Array
([
0x00
,
0x00
,
0x00
,
0x00
,
0xFF
]));
equal
(
32
,
expGolomb
.
skipLeadingZeros
(),
'32 leading zeros are dropped'
);
equal
(
8
,
expGolomb
.
bitsAvailable
(),
'8 bits remain'
);
equal
(
0xFF
,
expGolomb
.
readBits
(
8
),
'the second byte is read'
);
});
test
(
'drops working data when skipping leading zeros'
,
function
()
{
var
expGolomb
=
new
window
.
videojs
.
hls
.
ExpGolomb
(
new
Uint8Array
([
0x15
,
0xab
,
0x40
,
0xc8
,
0xFF
]));
equal
(
3
,
expGolomb
.
skipLeadingZeros
(),
'3 leading zeros are dropped'
);
equal
((
8
*
4
)
+
5
,
expGolomb
.
bitsAvailable
(),
'37 bits remain'
);
expGolomb
.
skipBits
(
1
);
equal
(
0x5a
,
expGolomb
.
readBits
(
8
),
'the next bits are read'
);
});
})(
this
);
test/video-js-hls.html
View file @
ced9b85
...
...
@@ -69,6 +69,7 @@
<script
src=
"video-js-hls_test.js"
></script>
<script
src=
"exp-golomb_test.js"
></script>
</head>
<body>
<div
id=
"qunit"
></div>
...
...
test/video-js-hls_test.js
View file @
ced9b85
...
...
@@ -67,16 +67,6 @@
console
.
log
(
'h264 tags:'
,
parser
.
stats
.
h264Tags
(),
'aac tags:'
,
parser
.
stats
.
aacTags
());
console
.
log
(
videojs
.
hls
.
utils
.
hexDump
(
parser
.
getFlvHeader
()));
for
(
i
=
0
;
i
<
4
;
++
i
)
{
parser
.
getNextTag
();
}
console
.
log
(
videojs
.
hls
.
utils
.
tagDump
(
parser
.
getNextTag
()));
console
.
log
(
'bad tag:'
);
for
(
i
=
0
;
i
<
3
;
++
i
)
{
console
.
log
(
videojs
.
hls
.
utils
.
tagDump
(
parser
.
getNextTag
()));
}
});
testAudioTag
=
function
(
tag
)
{
...
...
@@ -102,7 +92,10 @@
frameType
=
(
byte
&
0xF0
)
>>>
4
,
codecId
=
byte
&
0x0F
,
packetType
=
tag
.
bytes
[
12
],
compositionTime
=
(
tag
.
view
.
getInt32
(
13
)
&
0xFFFFFF00
)
>>
8
;
compositionTime
=
(
tag
.
view
.
getInt32
(
13
)
&
0xFFFFFF00
)
>>
8
,
nalHeader
;
// payload starts at tag.bytes[16]
// XXX: I'm not sure that frame types 3-5 are invalid
...
...
@@ -110,7 +103,7 @@
'the frame type should be valid'
);
equal
(
7
,
codecId
,
'the codec ID is AVC for h264'
);
ok
(
packetType
<=
2
&&
packetType
>=
0
,
'the packet type is within [0, 2]'
);
ok
(
packetType
<=
2
&&
packetType
>=
0
,
'the packet type is within [0, 2]'
);
if
(
packetType
!==
1
)
{
equal
(
0
,
compositionTime
,
...
...
@@ -118,7 +111,25 @@
}
// TODO: the rest of the bytes are an NLU unit
if
(
packetType
===
0
)
{
// AVC decoder configuration record
}
else
{
// NAL units
testNalUnit
(
tag
.
bytes
.
subarray
(
16
));
}
};
testNalUnit
=
function
(
bytes
)
{
var
nalHeader
=
bytes
[
0
],
unitType
=
nalHeader
&
0x1F
;
equal
(
0
,
(
nalHeader
&
0x80
)
>>>
7
,
'the first bit is always 0'
);
// equal(90, (nalHeader & 0x60) >>> 5, 'the NAL reference indicator is something');
// ok(unitType > 0, 'NAL unit type ' + unitType + ' is greater than 0');
// ok(unitType < 22 , 'NAL unit type ' + unitType + ' is less than 22');
};
asciiFromBytes
=
function
(
bytes
)
{
var
...
...
@@ -169,6 +180,7 @@
offset
++
;
}
else
{
// number
ok
(
!
isNaN
(
tag
.
view
.
getFloat64
(
offset
)),
'the value is not NaN'
);
offset
+=
8
;
}
}
...
...
Please
register
or
sign in
to post a comment