content: package android.media;
  
  import android.content.Context;
  import android.media.SubtitleController.Renderer;
  import android.os.Handler;
  import android.os.Message;
  import android.os.Parcel;
  import android.util.Log;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Vector;
  
  /** @hide */
  public class SRTRenderer extends Renderer {
      private final Context mContext;
      private final boolean mRender;
      private final Handler mEventHandler;
  
      private WebVttRenderingWidget mRenderingWidget;
  
      public SRTRenderer(Context context) {
          this(context, null);
      }
  
      SRTRenderer(Context mContext, Handler mEventHandler) {
          this.mContext = mContext;
          this.mRender = (mEventHandler == null);
          this.mEventHandler = mEventHandler;
      }
  
      @Override
      public boolean supports(MediaFormat format) {
          if (format.containsKey(MediaFormat.KEY_MIME)) {
              if (!format.getString(MediaFormat.KEY_MIME)
                      .equals(MediaPlayer.MEDIA_MIMETYPE_TEXT_SUBRIP)) {
                  return false;
              };
              return mRender == (format.getInteger(MediaFormat.KEY_IS_TIMED_TEXT, 0) == 0);
          }
          return false;
      }
  
      @Override
      public SubtitleTrack createTrack(MediaFormat format) {
          if (mRender && mRenderingWidget == null) {
              mRenderingWidget = new WebVttRenderingWidget(mContext);
          }
  
          if (mRender) {
              return new SRTTrack(mRenderingWidget, format);
          } else {
              return new SRTTrack(mEventHandler, format);
          }
      }
  }
  
  class SRTTrack extends WebVttTrack {
      private static final int MEDIA_TIMED_TEXT = 99;   // MediaPlayer.MEDIA_TIMED_TEXT
      private static final int KEY_STRUCT_TEXT = 16;    // TimedText.KEY_STRUCT_TEXT
      private static final int KEY_START_TIME = 7;      // TimedText.KEY_START_TIME
      private static final int KEY_LOCAL_SETTING = 102; // TimedText.KEY_START_TIME
  
      private static final String TAG = "SRTTrack";
      private final Handler mEventHandler;
  
      SRTTrack(WebVttRenderingWidget renderingWidget, MediaFormat format) {
          super(renderingWidget, format);
          mEventHandler = null;
      }
  
      SRTTrack(Handler eventHandler, MediaFormat format) {
          super(null, format);
          mEventHandler = eventHandler;
      }
  
      @Override
      protected void onData(SubtitleData data) {
          try {
              TextTrackCue cue = new TextTrackCue();
              cue.mStartTimeMs = data.getStartTimeUs() / 1000;
              cue.mEndTimeMs = (data.getStartTimeUs() + data.getDurationUs()) / 1000;
  
              String paragraph;
              paragraph = new String(data.getData(), "UTF-8");
              String[] lines = paragraph.split("\\r?\\n");
              cue.mLines = new TextTrackCueSpan[lines.length][];
  
              int i = 0;
              for (String line : lines) {
                  TextTrackCueSpan[] span = new TextTrackCueSpan[] {
                      new TextTrackCueSpan(line, -1)
                  };
                  cue.mLines[i++] = span;
              }
  
              addCue(cue);
          } catch (UnsupportedEncodingException e) {
              Log.w(TAG, "subtitle data is not UTF-8 encoded: " + e);
          }
      }
  
      @Override
      public void onData(byte[] data, boolean eos, long runID) {
          // TODO make reentrant
          try {
              Reader r = new InputStreamReader(new ByteArrayInputStream(data), "UTF-8");
              BufferedReader br = new BufferedReader(r);
  
              String header;
              while ((header = br.readLine()) != null) {
                  // discard subtitle number
                  header  = br.readLine();
                  if (header == null) {
                      break;
                  }
  
                  TextTrackCue cue = new TextTrackCue();
                  String[] startEnd = header.split("-->");
                  cue.mStartTimeMs = parseMs(startEnd[0]);
                  cue.mEndTimeMs = parseMs(startEnd[1]);
                  cue.mRunID = runID;
  
                  String s;
                  List<String> paragraph = new ArrayList<String>();
                  while (!((s = br.readLine()) == null || s.trim().equals(""))) {
                      paragraph.add(s);
                  }
  
                  int i = 0;
                  cue.mLines = new TextTrackCueSpan[paragraph.size()][];
                  cue.mStrings = paragraph.toArray(new String[0]);
                  for (String line : paragraph) {
                      TextTrackCueSpan[] span = new TextTrackCueSpan[] {
                              new TextTrackCueSpan(line, -1)
                      };
                      cue.mStrings[i] = line;
                      cue.mLines[i++] = span;
                  }
  
                  addCue(cue);
              }
  
          } catch (UnsupportedEncodingException e) {
              Log.w(TAG, "subtitle data is not UTF-8 encoded: " + e);
          } catch (IOException ioe) {
              // shouldn't happen
              Log.e(TAG, ioe.getMessage(), ioe);
          }
      }
  
      @Override
      public void updateView(Vector<Cue> activeCues) {
          if (getRenderingWidget() != null) {
              super.updateView(activeCues);
              return;
          }
  
          if (mEventHandler == null) {
              return;
          }
  
          for (Cue cue : activeCues) {
              TextTrackCue ttc = (TextTrackCue) cue;
  
              Parcel parcel = Parcel.obtain();
              parcel.writeInt(KEY_LOCAL_SETTING);
              parcel.writeInt(KEY_START_TIME);
              parcel.writeInt((int) cue.mStartTimeMs);
  
              parcel.writeInt(KEY_STRUCT_TEXT);
              StringBuilder sb = new StringBuilder();
              for (String line : ttc.mStrings) {
                  sb.append(line).append('\n');
              }
  
              byte[] buf = sb.toString().getBytes();
              parcel.writeInt(buf.length);
              parcel.writeByteArray(buf);
  
              Message msg = mEventHandler.obtainMessage(MEDIA_TIMED_TEXT, 0 /* arg1 */, 0 /* arg2 */,
                      parcel);
              mEventHandler.sendMessage(msg);
          }
          activeCues.clear();
      }
  
      private static long parseMs(String in) {
          long hours = Long.parseLong(in.split(":")[0].trim());
          long minutes = Long.parseLong(in.split(":")[1].trim());
          long seconds = Long.parseLong(in.split(":")[2].split(",")[0].trim());
          long millies = Long.parseLong(in.split(":")[2].split(",")[1].trim());
  
          return hours * 60 * 60 * 1000 + minutes * 60 * 1000 + seconds * 1000 + millies;
  
      }
  }
  