class SubripDecoder extends SimpleSubtitleDecoder {

  @Override
  protected SubripSubtitle decode(byte[] bytes, int length, boolean reset) {
    ArrayList<Cue> cues = new ArrayList<>();
    LongArray cueTimesUs = new LongArray();
    ParsableByteArray subripData = new ParsableByteArray(bytes, length);
    String currentLine;

    while ((currentLine = subripData.readLine()) != null) {
      if (currentLine.length() == 0) {
        // Skip blank lines.
        continue;
      }

      // Parse the index line as a sanity check.
      try {
        Integer.parseInt(currentLine);
      } catch (NumberFormatException e) {
        Log.w(TAG, "Skipping invalid index: " + currentLine);
        continue;
      }

      // Read and parse the timing line.
      boolean haveEndTimecode = false;
      currentLine = subripData.readLine();
      if (currentLine == null) {
        Log.w(TAG, "Unexpected end");
        break;
      }

      Matcher matcher = SUBRIP_TIMING_LINE.matcher(currentLine);
      if (matcher.matches()) {
        cueTimesUs.add(parseTimecode(matcher, 1));
        if (!TextUtils.isEmpty(matcher.group(6))) {
          haveEndTimecode = true;
          cueTimesUs.add(parseTimecode(matcher, 6));
        }
      } else {
        Log.w(TAG, "Skipping invalid timing: " + currentLine);
        continue;
      }

      // Read and parse the text and tags.
      textBuilder.setLength(0);
      tags.clear();
      while (!TextUtils.isEmpty(currentLine = subripData.readLine())) {
        if (textBuilder.length() > 0) {
          textBuilder.append("<br>");
        }
        textBuilder.append(processLine(currentLine, tags));
      }

      Spanned text = Html.fromHtml(textBuilder.toString());

      String alignmentTag = null;
      for (int i = 0; i < tags.size(); i++) {
        String tag = tags.get(i);
        if (tag.matches(SUBRIP_ALIGNMENT_TAG)) {
          alignmentTag = tag;
          // Subsequent alignment tags should be ignored.
          break;
        }
      }
      cues.add(buildCue(text, alignmentTag));

      if (haveEndTimecode) {
        cues.add(null);
      }
    }

    Cue[] cuesArray = new Cue[cues.size()];
    cues.toArray(cuesArray);
    long[] cueTimesUsArray = cueTimesUs.toArray();
    return new SubripSubtitle(cuesArray, cueTimesUsArray);
  }

  public  SubripDecoder();

}