Skip to content

Commit

Permalink
Merge pull request #488 from steve6/feature/sei_multiple_cc
Browse files Browse the repository at this point in the history
add support for CC 608/708 when there are multiple payloads inside sei packet
  • Loading branch information
mangui committed Mar 9, 2016
2 parents 3b9e481 + 6866f29 commit 7168b97
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 102 deletions.
47 changes: 47 additions & 0 deletions src/org/mangui/hls/demux/Nalu.as
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,52 @@
public static function get AUD():ByteArray {
return _audNalu;
}

private static function findNextUnescapeIndex(bytes : ByteArray, offset:int, limit:int):int {
for (var i:int = offset; i < limit - 2; i++) {
if (bytes[i] == 0x00 && bytes[i + 1] == 0x00 && bytes[i + 2] == 0x03) {
return i;
}
}
return limit;
}

private static function arrayCopy(src:ByteArray, srcPos:int, dest:ByteArray, destPos:int, length:int):void {
var iterations:int = Math.min(Math.min(length, src.length - srcPos), dest.length - destPos);
for(var i:int = 0; i < iterations; i++)
dest[destPos + i] = src[srcPos + i];
}

public static function unescapeStream(data : ByteArray, position: int,limit: uint):int {
var scratchEscapeCount:int = 0;
var scratchEscapePositions:Array = new Array();

while (position < limit) {
position = findNextUnescapeIndex(data, position, limit);
if (position < limit) {
scratchEscapeCount++;
scratchEscapePositions.push(position);
position += 3;
}
}

var unescapedLength:int = limit - scratchEscapeCount;
var escapedPosition:int = 0; // The position being read from.
var unescapedPosition:int = 0; // The position being written to.
for (var i:int = 0; i < scratchEscapeCount; i++) {
var nextEscapePosition:int = scratchEscapePositions[i];
var copyLength:int = nextEscapePosition - escapedPosition;
arrayCopy(data, escapedPosition, data, unescapedPosition, copyLength);
unescapedPosition += copyLength;
data[unescapedPosition++] = 0;
data[unescapedPosition++] = 0;
escapedPosition += copyLength + 3;
}

var remainingLength:int = unescapedLength - unescapedPosition;
arrayCopy(data, escapedPosition, data, unescapedPosition, remainingLength);

return unescapedLength;
}
}
}
221 changes: 119 additions & 102 deletions src/org/mangui/hls/demux/TSDemuxer.as
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,93 @@ package org.mangui.hls.demux {
return null;
}

//Read CC track
private function readCC(pes : PES):void
{
var country_code : uint = pes.data.readUnsignedByte();

if (country_code == 181)
{
var provider_code : uint = pes.data.readUnsignedShort();

if (provider_code == 49)
{
var user_structure : uint = pes.data.readUnsignedInt();

if (user_structure == 0x47413934) // GA94
{
var user_data_type : uint = pes.data.readUnsignedByte();

// CEA-608 wrapped in 708 ( user_data_type == 4 is raw 608, not handled yet )
if (user_data_type == 3)
{
// cc -- the first 8 bits are 1-Boolean-0 and the 5 bits for the number of CCs
var byte:uint = pes.data.readUnsignedByte();

// get the total number of cc_datas
var total:uint = 31 & byte;
var count:uint = 0;

// supposedly a flag to process the cc_datas or not
// isn't working for me, so i don't use it yet
var process:Boolean = !((64 & byte) == 0);

var size:uint = total * 3;

// em_data, do we need? It's not used for anything, but it's there, so i need to pull it out
var otherByte:uint = pes.data.readUnsignedByte();

if (pes.data.bytesAvailable >= size)
{
// ByteArray for onCaptionInfo event
var sei : ByteArray = new ByteArray();

// onCaptionInfo payloads need to know the size of the binary data
// there's two two bytes we just read, plus the cc_datas, which are 3 bytes each
sei.writeUnsignedInt(2+3*total);

// write those two bytes
sei.writeByte(byte);
sei.writeByte(otherByte);

// write the cc_datas
pes.data.readBytes(sei, 6, 3*total);

pes.data.position -= total * 3;

// onCaptionInfo expects Base64 data...
var sei_data:String = Base64.encode(sei);

var cc_data:Object = {
type: "708",
data: sei_data
};

// add a new FLVTag with the onCaptionInfo call
var tag:FLVTag = new FLVTag(FLVTag.METADATA, pes.pts, pes.pts, false);

var data : ByteArray = new ByteArray();
data.objectEncoding = ObjectEncoding.AMF0;
data.writeObject("onCaptionInfo");
data.objectEncoding = ObjectEncoding.AMF3;
data.writeByte(0x11);
data.writeObject(cc_data);
tag.push(data, 0, data.length);
tag.build();
_tags.push(tag);
}
else
{
CONFIG::LOGGING {
Log.warn("not enough bytes to extract caption!");
}
}
}
}
}
}
}

/** Parse a limited amount of packets each time to avoid blocking **/
private function _parseTimer(e : Event) : void {
var start_time : int = getTimer();
Expand Down Expand Up @@ -525,108 +612,38 @@ package org.mangui.hls.demux {
pes.data.readBytes(pps, 0, frame.length);
ppsvect.push(pps);
} else if (frame.type == 6) {

// We already know it's 6, so skip first byte
pes.data.position = frame.start + 1;

// we need at least 12 bytes to retrieve Caption length
if(pes.data.bytesAvailable > 12) {
// get the SEI payload type
var payload_type : uint = pes.data.readUnsignedByte();

if (payload_type == 4)
{
var payload_size : uint = 0;

do {
payload_size = pes.data.readUnsignedByte();
}
while(payload_size === 255)

var country_code : uint = pes.data.readUnsignedByte();

if (country_code == 181)
{
var provider_code : uint = pes.data.readUnsignedShort();

if (provider_code == 49)
{
var user_structure : uint = pes.data.readUnsignedInt();

if (user_structure == 0x47413934) // GA94
{
var user_data_type : uint = pes.data.readUnsignedByte();

// CEA-608 wrapped in 708 ( user_data_type == 4 is raw 608, not handled yet )
if (user_data_type == 3)
{
// cc -- the first 8 bits are 1-Boolean-0 and the 5 bits for the number of CCs
var byte:uint = pes.data.readUnsignedByte();

// get the total number of cc_datas
var total:uint = 31 & byte;
var count:uint = 0;

// supposedly a flag to process the cc_datas or not
// isn't working for me, so i don't use it yet
var process:Boolean = !((64 & byte) == 0);

var size:uint = total * 3;

// em_data, do we need? It's not used for anything, but it's there, so i need to pull it out
var otherByte:uint = pes.data.readUnsignedByte();

if (pes.data.bytesAvailable >= size)
{
// ByteArray for onCaptionInfo event
var sei : ByteArray = new ByteArray();

// onCaptionInfo payloads need to know the size of the binary data
// there's two two bytes we just read, plus the cc_datas, which are 3 bytes each
sei.writeUnsignedInt(2+3*total);

// write those two bytes
sei.writeByte(byte);
sei.writeByte(otherByte);

// write the cc_datas
pes.data.readBytes(sei, 6, 3*total);

pes.data.position -= total * 3;

// onCaptionInfo expects Base64 data...
var sei_data:String = Base64.encode(sei);

var cc_data:Object = {
type: "708",
data: sei_data
};

// add a new FLVTag with the onCaptionInfo call
var tag:FLVTag = new FLVTag(FLVTag.METADATA, pes.pts, pes.pts, false);

var data : ByteArray = new ByteArray();
data.objectEncoding = ObjectEncoding.AMF0;
data.writeObject("onCaptionInfo");
data.objectEncoding = ObjectEncoding.AMF3;
data.writeByte(0x11);
data.writeObject(cc_data);
tag.push(data, 0, data.length);
tag.build();
_tags.push(tag);
}
else
{
CONFIG::LOGGING {
Log.warn("not enough bytes to extract caption!");
}
}
}
}
}
}
}
}

//unescape Emulation Prevention bytes
Nalu.unescapeStream(pes.data,frame.start,frame.start + frame.length);

// We already know it's 6, so skip first byte
pes.data.position = frame.start + 1;

// we need at least 12 bytes to retrieve Caption length
if(pes.data.bytesAvailable > 12) {

// get the SEI payload type
var payload_type : uint = 0;
var payload_size : uint = 0;
while (pes.data.position < frame.start + frame.length) {
// Parse payload type.
payload_type= 0;
do {
payload_type += pes.data.readUnsignedByte();
} while (payload_type == 0xFF);
// Parse payload size.
payload_size = 0;
do {
payload_size += pes.data.readUnsignedByte();
} while (pes.data.bytesAvailable!=0 && payload_size == 0xFF);
// Process the payload. We only support EIA-608 payloads currently.
if (payload_type == 4) {
readCC(pes);
} else {
pes.data.position+=payload_size;
}
}
}
} else if (frame.type == 0) {
// report parsing error
if(_callback_error != null) {
Expand Down

0 comments on commit 7168b97

Please sign in to comment.