Commit ac988740 by Julian Cable

move header into track.output.format object and then use it in the decoder create method.

This doesn't make a stateless decoder but it is a step in the right direction.
Note that subtitles are not rendering. Is there something wrong with the timecodes?
parent ef2d7c7f
......@@ -19,7 +19,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1'
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.novoda:bintray-release:0.3.4'
}
}
......
......@@ -352,6 +352,10 @@
"name": "Misc",
"samples": [
{
"name": "Watashi ga Motete Dousunda - 01 SSA",
"uri": "http://192.168.1.133:8080/Watashi ga Motete Dousunda - 01.mkv"
},
{
"name": "Dizzy",
"uri": "http://html5demos.com/assets/dizzy.mp4"
},
......
......@@ -305,9 +305,18 @@ public final class Format implements Parcelable {
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, null, selectionFlags, language,
NO_VALUE, drmInitData, subsampleOffsetUs);
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate,
List<byte[]> initializationData,
@C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs, null,
NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs, initializationData,
drmInitData, null);
}
......
......@@ -1110,13 +1110,8 @@ public final class MatroskaExtractor implements Extractor {
}
private void writeSSASample(Track track) {
StringBuffer s = new StringBuffer();
if(track.ssaHeader != null) {
// header contains the original format but the Matroska encoder changes this.
SSADecoder.writeMangledHeader(s, track.ssaHeader);
}
SSADecoder.buildDialogue(s, track.ssaSample, blockDurationUs);
ParsableByteArray out = new ParsableByteArray(s.toString().getBytes());
String s = SSADecoder.buildDialogue(track.ssaSample, blockDurationUs);
ParsableByteArray out = new ParsableByteArray(s.getBytes());
track.output.sampleData(out, out.limit());
sampleBytesWritten += out.limit();
}
......@@ -1382,7 +1377,6 @@ public final class MatroskaExtractor implements Extractor {
public boolean flagForced;
public boolean flagDefault = true;
private String language = "eng";
public byte[] ssaHeader = null;
public String ssaSample = null;
// Set when the output is initialized. nalUnitLengthFieldLength is only set for H264/H265.
......@@ -1504,7 +1498,7 @@ public final class MatroskaExtractor implements Extractor {
break;
case CODEC_ID_ASS:
mimeType = MimeTypes.TEXT_SSA;
ssaHeader = codecPrivate;
initializationData = Collections.singletonList(codecPrivate);
break;
case CODEC_ID_VOBSUB:
mimeType = MimeTypes.APPLICATION_VOBSUB;
......@@ -1548,8 +1542,7 @@ public final class MatroskaExtractor implements Extractor {
Format.NO_VALUE, initializationData, language, drmInitData);
} else if (MimeTypes.TEXT_SSA.equals(mimeType)) {
format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
Format.NO_VALUE, selectionFlags, language, drmInitData);
output.track(number).sampleData(new ParsableByteArray(codecPrivate), codecPrivate.length);
Format.NO_VALUE, initializationData, selectionFlags, language, Format.NO_VALUE, drmInitData, Format.NO_VALUE);
} else {
throw new ParserException("Unexpected MIME type.");
}
......
......@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.text;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.text.cea.Cea608Decoder;
import com.google.android.exoplayer2.text.ssa.SSADecoder;
import com.google.android.exoplayer2.text.subrip.SubripDecoder;
import com.google.android.exoplayer2.text.ttml.TtmlDecoder;
import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder;
......@@ -24,6 +25,8 @@ import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder;
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder;
import com.google.android.exoplayer2.util.MimeTypes;
import static android.R.attr.mimeType;
/**
* A factory for {@link SubtitleDecoder} instances.
*/
......@@ -75,10 +78,15 @@ public interface SubtitleDecoderFactory {
if (clazz == null) {
throw new IllegalArgumentException("Attempted to create decoder for unsupported format");
}
if(clazz == SSADecoder.class) {
return clazz.asSubclass(SubtitleDecoder.class).getConstructor(byte[].class)
.newInstance(format.initializationData.get(0));
}
if (clazz == Cea608Decoder.class) {
return clazz.asSubclass(SubtitleDecoder.class).getConstructor(String.class, Integer.TYPE)
.newInstance(format.sampleMimeType, format.accessibilityChannel);
} else {
}
else {
return clazz.asSubclass(SubtitleDecoder.class).getConstructor().newInstance();
}
} catch (Exception e) {
......
......@@ -11,7 +11,9 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import static android.R.attr.data;
import static android.R.attr.subtitle;
import static android.R.attr.x;
/**
* Created by cablej01 on 26/12/2016.
......@@ -58,21 +60,33 @@ import static android.R.attr.subtitle;
than the previous one, the value passed to getCues will go down.
*/
/**
* A {@link SimpleSubtitleDecoder} for ASS/SSA.
*/
public class SSADecoder extends SimpleSubtitleDecoder {
private static final String TAG = "SSADecoder";
private static String defaultDialogueFormat = "Start, End, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text";
private static String defaultDialogueFormat = "Start, End, ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text";
private static String defaultStyleFormat = "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding";
private String[] dialogueFormat;
private String[] styleFormat;
private Map<String,Style> styles = new HashMap<>();
// 0,0,Watamote-internal/narrator,Serinuma,0000,0000,0000, ,The prince should be with the princess.
// , ,style ,name ,L ,R, V ,Effect, text
public SSADecoder() {
super("SSADecoder");
dialogueFormat = parseKeys(defaultDialogueFormat);
styleFormat = parseKeys(defaultStyleFormat);
}
public SSADecoder(byte[] header) {
super("SSADecoder");
styleFormat = parseKeys(defaultStyleFormat);
decodeHeader(header, header.length);
// put back the Matroska format
dialogueFormat = parseKeys(defaultDialogueFormat);
}
/**
* Decodes data into a {@link SSASubtitle}.
*
......@@ -183,22 +197,8 @@ public class SSADecoder extends SimpleSubtitleDecoder {
return result;
}
public static void writeMangledHeader(StringBuffer s, byte[] data){
// header contains the original format but the Matroska encoder changes this.
// we won't need anything after the [Events] line
try {
String header = new String(data, "UTF-8").split("\\[Events]")[0];
s.append(header);
}
catch (UnsupportedEncodingException e) {
// we know this can't happen
}
s.append("[Events]\n");
s.append(defaultDialogueFormat);
s.append("\n");
}
public static void buildDialogue(StringBuffer s, String data, long durationUs) {
public static String buildDialogue(String data, long durationUs) {
StringBuffer s = new StringBuffer();
s.append("Dialogue: ");
s.append(SSADecoder.formatTimeCode(0)); // blockTimeUs
s.append(",");
......@@ -210,6 +210,7 @@ public class SSADecoder extends SimpleSubtitleDecoder {
s.append(",");
s.append(data);
s.append("\n");
return s.toString();
}
public static String formatTimeCode(long tc_us) {
......
......@@ -11,6 +11,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static android.R.attr.start;
/**
* Created by cablej01 on 26/12/2016.
*/
......@@ -91,7 +93,8 @@ public class SSASubtitle implements Subtitle {
String effect = ev.get("effect");
String text = ev.get("text").replaceAll("\\\\N", "\n");
String simpleText = text.replaceAll("\\{[^{]*\\}", "");
Cue cue = new SSACue(text, style, layer, effect);
//Cue cue = new SSACue(text, style, layer, effect);
Cue cue = new Cue(simpleText);
long start = SSADecoder.parseTimecode(ev.get("start"));
cueTimesUs.add(start);
cues.add(cue);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment