Skip to content

Commit

Permalink
Update to fix multiple ttiBlocks and timing error
Browse files Browse the repository at this point in the history
  • Loading branch information
hurdlea committed Jun 23, 2020
1 parent a662d3a commit 30c5418
Show file tree
Hide file tree
Showing 33 changed files with 3,743 additions and 3,719 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/CaptionLine.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/CaptionMessage.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/ConvertSTL.class
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/LineFormat.class
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/StlGsiBlock.class
Binary file not shown.
Binary file not shown.
Binary file modified bin/au/com/foxtel/product/subtitleTools/StlTtiBlock.class
Binary file not shown.
24 changes: 13 additions & 11 deletions src/au/com/foxtel/product/subtitleTools/CaptionLine.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package au.com.foxtel.product.subtitleTools

import groovy.xml.MarkupBuilder

import java.util.regex.Matcher


class CaptionLine {
Boolean empty = true
Expand Down Expand Up @@ -31,30 +33,30 @@ class CaptionLine {
format.colour = ebuColours[it as byte]
}
format.text += ' '
break;
break

case 0x1d: // background colour change
backgroundChange = true
format.text += ' '
break;
break

case [0x0a, 0x8f, 0x8a]: // line termination
if (!format.text.trim().empty) {
this.text.add(format)
format = new LineFormat()
}
break;
break

case 0x20..0x7e:
case 0xa0..0xff: // regular characters
int chr = mapCharacter((int) it & 0xff)
format.text += new String( chr as int[], 0, 1)
break;
break

default:
// add a space to replace the control character
format.text += ' '
break;
break
}
}

Expand All @@ -63,7 +65,7 @@ class CaptionLine {
}
}

def String toString()
String toString()
{
def output = ""
text.each {
Expand All @@ -72,12 +74,12 @@ class CaptionLine {
"row:" + row + " " + output
}

def String toTTML(MarkupBuilder xml)
String toTTML(MarkupBuilder xml)
{
boolean removeSpace = true
text.each {
String caption = it.text
def m
Matcher m
if (removeSpace) {
if ((m = it.text =~ /(\s+)(.+)/)) {

Expand All @@ -90,7 +92,7 @@ class CaptionLine {
}
}

def String toVTT()
String toVTT()
{
def output = ""
text.each {
Expand All @@ -114,9 +116,9 @@ class CaptionLine {
}

// Fix character mapping differences between EBU Latin and regular Latin set
def int mapCharacter(int chr)
static int mapCharacter(int chr)
{
int mapped = 0
int mapped
switch(chr) {
case 0x24: // Swap currency symbol for $ sign
mapped = 0xa4
Expand Down
26 changes: 13 additions & 13 deletions src/au/com/foxtel/product/subtitleTools/CaptionMessage.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class CaptionMessage {
int startOfMessage = 0
int endOfMessage = 0

def ebuTextField(StlTtiBlock message)
void ebuTextField(StlTtiBlock message)
{
int row = message.verticalPosition
startOfMessage = message.timecodeIn
Expand All @@ -27,7 +27,7 @@ class CaptionMessage {
}
}

def ArrayList<ArrayList<Byte>> splitLines(byte[] textField)
static ArrayList<ArrayList<Byte>> splitLines(byte[] textField)
{
int row = 0
ArrayList<ArrayList<Byte>> rows = new ArrayList<ArrayList<Byte>>()
Expand All @@ -48,10 +48,10 @@ class CaptionMessage {
return rows
}

def String toTTML(MarkupBuilder xml, int offset)
String toTTML(MarkupBuilder xml, int offset)
{
boolean topRegion = true
int renderRow = 1;
int renderRow = 1

if (lines[0].row < 13) {
topRegion = true
Expand Down Expand Up @@ -86,15 +86,15 @@ class CaptionMessage {
}
}

def String toVTT(int offset)
String toVTT(int offset)
{
def output = ""
String output = ""

// Render the text
output += framesToIsoTime(startOfMessage + offset) + " --> " +
framesToIsoTime(endOfMessage + offset) + " " +
"line:" + ((lines[0].row >> 1) + 1) + " " +
"align:middle\n"
"line:" + (int) (((lines[0].row + 3) / 30) * 100) + "% " +
"align:middle position:50% size:80%\n"
lines.each {
output += it.toVTT()
}
Expand All @@ -103,7 +103,7 @@ class CaptionMessage {
return output
}

def String toString()
String toString()
{
def output = ""
lines.each {
Expand All @@ -112,15 +112,15 @@ class CaptionMessage {
"SOM: " + framesToIsoTime(this.startOfMessage) + " EOM: " + framesToIsoTime(this.endOfMessage) + "\n" + output
}

def String framesToIsoTime(int frames)
static String framesToIsoTime(int frames)
{

String output = ""

output += sprintf("%02d:", (int) (frames / (3600 * 25)))
output += sprintf("%02d:", Math.round(frames / (60 * 25)).intValue() % 60)
output += sprintf("%02d.", Math.round(frames / 25).intValue() % 60)
output += sprintf("%03d", (frames % 25).intValue() * 40)
output += sprintf("%02d:", (int) (frames / (60 * 25)).intValue() % 60)
output += sprintf("%02d.", (int) (frames / 25).intValue() % 60)
output += sprintf("%03d", (int) (frames % 25) * 40)

output
}
Expand Down
34 changes: 22 additions & 12 deletions src/au/com/foxtel/product/subtitleTools/ConvertSTL.groovy
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package au.com.foxtel.product.subtitleTools

import groovy.xml.MarkupBuilder

import java.nio.ByteBuffer

import groovy.xml.XmlUtil
Expand All @@ -18,10 +20,11 @@ class ConvertSTL {
while (contents.position() < contents.capacity())
{
StlTtiBlock ttiBlock = new StlTtiBlock()
byte[] ttiBytes = new byte[128]
contents.get(ttiBytes, 0, 128)
ttiBlock.parse(ttiBytes)

while(ttiBlock.extensionBlockNumber != 0xff) {
byte[] ttiBytes = new byte[128]
contents.get(ttiBytes, 0, 128)
ttiBlock.parse(ttiBytes)
}
CaptionMessage caption = new CaptionMessage()
caption.ebuTextField(ttiBlock)
if (!caption.lines.isEmpty()) {
Expand All @@ -33,28 +36,35 @@ class ConvertSTL {
static String getTTML(ArrayList captions, int offset = 0)
{
def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)
xml.setDoubleQuotes(true);
def xml = new MarkupBuilder(writer)
xml.setDoubleQuotes(true)

xml.mkp.xmlDeclaration(version:"1.0", encoding:"UTF-8")
xml.tt(
"xmlns:ttp":"http://www.w3.org/ns/ttml#parameter",
'xmlns:tts':"http://www.w3.org/ns/ttml#syling",
'xmlns':"http://www.w3.org/ns/ttml",
'xmlns:smpte':"http://www.smpte-ra.org/schema/2052-1/2010/smpte-tt",
'xmlns:ebutts':"urn:ebu:tt:style",
'xmlns:xsi':"http://www.w3.org/2001/XMLSchema-instance",
'ttp:timebase':"media",
'xml:lang':"english",
'xml:lang':"en",
'ttp:cellResolution':"50 30"
) {
head() {
styling() {
style(
'xml:id':"teletext",
'tts:fontFamily':"monospaceSansSerif",
'tts:fontSize':"160%",
'tts:fontSize':"125%",
'tts:textAlign':"left",
'tts:lineHeight':"125%",
'tts:backgroundColor':"transparent")
'tts:fontStyle':"normal",
'tts:lineHeight':"normal",
'tts:wrapOption':"noWrap",
'tts:color':"#ffffff",
'tts:showBackground':"whenActive",
'tts:backgroundColor':"transparent",
'ebutts:linePadding':'0.5c'
)
}
layout() {
region(
Expand Down Expand Up @@ -100,7 +110,7 @@ class ConvertSTL {
def offset = args[1] ?: "0"
offset = Integer.parseInt(offset)

processFile(args[0], captions)
processFile(file, captions)

def ttml_captions = getTTML(captions, offset)
def ttml = new File(args[0] + ".ttml").newWriter()
Expand Down
8 changes: 4 additions & 4 deletions src/au/com/foxtel/product/subtitleTools/stlGsiBlock.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class StlGsiBlock {
this.userDefinedArea = getString(data[448..1023])
}

def getDate(List<Byte> data)
static Date getDate(List<Byte> data)
{
def string = getString(data)
if (string == "")
Expand All @@ -79,21 +79,21 @@ class StlGsiBlock {
format.parse(string)
}

def getString(List<Byte> data)
static String getString(List<Byte> data)
{
String string = new String(data as byte[], "US-ASCII")
//println "[" + string + "]"
string.trim()
}

def getCharAsString(Byte data)
static String getCharAsString(Byte data)
{
String string = new String(data as byte[], "US-ASCII")
//println "[" + string + "]"
string.trim()
}

def StringToFrames(byte[] data)
static int StringToFrames(byte[] data)
{
int hours = getString(data[0..1]).toInteger()
int minutes = getString(data[2..3]).toInteger()
Expand Down
40 changes: 26 additions & 14 deletions src/au/com/foxtel/product/subtitleTools/stlTtiBlock.groovy
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package au.com.foxtel.product.subtitleTools

import java.util.List;
import java.nio.ByteBuffer
import java.nio.CharBuffer

class StlTtiBlock {
int subtitleGroupNumber
Expand All @@ -13,9 +14,10 @@ class StlTtiBlock {
int justificationCode
int commentFlag
byte[] textField

void parse(byte[] record)
{
if (textField)
this.subtitleGroupNumber = ucharToInt(record[0])
this.subtitleNumber = ucharToInt(record[1]) + (ucharToInt(record[2]) << 8)
this.extensionBlockNumber = ucharToInt(record[3])
Expand All @@ -25,35 +27,45 @@ class StlTtiBlock {
this.verticalPosition = ucharToInt(record[13])
this.justificationCode = ucharToInt(record[14])
this.commentFlag = ucharToInt(record[15])
this.textField = record[16..127] as byte[]
// When there are extension blocks accumulate the text portion
if (this.textField) {
byte[] buffer = new byte[this.textField.length + 112]
System.arraycopy(this.textField, 0, buffer, 0, this.textField.length)
System.arraycopy(record, 16, buffer, this.textField.length, 112)
this.textField = buffer
} else {
this.textField = record[16..127] as byte[]
}
}

def ucharToInt(byte b)
def static ucharToInt(byte b)
{
(int) (b & 0xff)
(int) (b & 0x00ff)
}

def getTimecode(List<Byte> data)


def static getTimecode(List<Byte> data)
{
(data[0] * (3600 * 25)) + (data[1] * (60 * 25)) + (data[2] * 25) + data[3]
}

def String toString()
String toString()
{
"[sn:" + subtitleNumber + " eb:" + extensionBlockNumber + " tcin:" + timecodeIn + " tcout:" + timecodeOut + " text:" + makePrintable(textField) + "]"
}

def String makePrintable(byte[] text)
static String makePrintable(byte[] text)
{
def output = ""
text.each {
switch(ucharToInt(it))
String output
CharBuffer charBuffer = ByteBuffer.wrap(text).asCharBuffer()
charBuffer.each {
switch(it.toInteger())
{
case 0x20..0x7e:
output += (char) it
output += it
break
default:
output += "[#" + Integer.toHexString(it & 0xff) + "]"
output += "[#" + Integer.toHexString(it.toInteger()) + "]"
}
}
output
Expand Down
Loading

0 comments on commit 30c5418

Please sign in to comment.