LoginSignup
4
3

More than 5 years have passed since last update.

ExoplayerでMPEG-DASH + PlayReadyの動画を再生するためのメモ

Last updated at Posted at 2017-01-10

はじめに

Exoplayerのsupported-formatsを見るとMPEG-DASH + PlayReadyの動画が再生できるように見えるのですが、実際に再生しようとしたらうまく出来ませんでした・・・。
試行錯誤の末、なんとか出来るようになったためメモ。

注意:厳密に検証は行っていないため、自己責任でお願いします。

追記:Exoplayerにissueをあげたところ、PlayReadyは<cenc:pssh>elementと<mspr:pro>elementを使用でき、exoplayerは<cenc:pssh>elementのみ対応しているとのこと。
私のように使用したパッケージャーが<mspr:pro>elementしか出力しない場合、<mspr:pro>elementをパースする処理が必要となるようです・・・。

更に追記:Exoplayer v2系には<mspr:pro>対応が取り込まれたため、下記対応はv1系のみで良くなりました。

問題と修正箇所

エラーの発生箇所を調べていたら、Manifestファイルのパース時にPlayReady用の処理が書かれていないことが判明。
対応しているんじゃなかったのかいヾ(`ω´)ノ プンスカ

という訳でWidevineのパースしている箇所と、SmoothStreamingでPlayReadyを処理している箇所を調べて、試行錯誤した結果がこちらです。

Exoplayer 1.x系

MediaPresentationDescriptionParser.java
  protected ContentProtection parseContentProtection(XmlPullParser xpp)
      throws XmlPullParserException, IOException {
    String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
    UUID uuid = null;
    SchemeInitData data = null;
    boolean seenPsshElement = false;
    do {
      xpp.next();
      // The cenc:pssh element is defined in 23001-7:2015.
      if (ParserUtil.isStartTag(xpp, "cenc:pssh") && xpp.next() == XmlPullParser.TEXT) {
        seenPsshElement = true;
        data = new SchemeInitData(MimeTypes.VIDEO_MP4,
            Base64.decode(xpp.getText(), Base64.DEFAULT));
        uuid = PsshAtomUtil.parseUuid(data.data);
      }
      // ----- Add start -----
      if (ParserUtil.isStartTag(xpp, "mspr:pro") && xpp.next() == XmlPullParser.TEXT) {
        seenPsshElement = true;
        uuid = UUID.fromString(schemeIdUri.split(":")[2]);
        data = new SchemeInitData(MimeTypes.VIDEO_MP4,
                PsshAtomUtil.buildPsshAtom(uuid,Base64.decode(xpp.getText(), Base64.DEFAULT)));
      }
      // ----- Add end ----- 
    } while (!ParserUtil.isEndTag(xpp, "ContentProtection"));
    if (seenPsshElement && uuid == null) {
      Log.w(TAG, "Skipped unsupported ContentProtection element");
      return null;
    }
    return buildContentProtection(schemeIdUri, uuid, data);
  }

なお、Exoplayer 2.x系でも使えます。

DashManifestParser.java
  protected SchemeData parseContentProtection(XmlPullParser xpp) throws XmlPullParserException,
      IOException {
    String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri"); // Add
    byte[] data = null;
    UUID uuid = null;
    boolean seenPsshElement = false;
    boolean requiresSecureDecoder = false;
    do {
      xpp.next();
      // The cenc:pssh element is defined in 23001-7:2015.
      if (XmlPullParserUtil.isStartTag(xpp, "cenc:pssh") && xpp.next() == XmlPullParser.TEXT) {
        seenPsshElement = true;
        data = Base64.decode(xpp.getText(), Base64.DEFAULT);
        uuid = PsshAtomUtil.parseUuid(data);
      } else if (XmlPullParserUtil.isStartTag(xpp, "widevine:license")) {
        String robustnessLevel = xpp.getAttributeValue(null, "robustness_level");
        requiresSecureDecoder = robustnessLevel != null && robustnessLevel.startsWith("HW");
      // ----- Add start -----
      } else if (ParserUtil.isStartTag(xpp, "mspr:pro") && xpp.next() == XmlPullParser.TEXT) {
        seenPsshElement = true;
        uuid = UUID.fromString(schemeIdUri.split(":")[2]);
        data = new SchemeInitData(MimeTypes.VIDEO_MP4,
                PsshAtomUtil.buildPsshAtom(uuid,Base64.decode(xpp.getText(), Base64.DEFAULT)));
      }
      // ----- Add end ----- 
    } while (!XmlPullParserUtil.isEndTag(xpp, "ContentProtection"));
    if (!seenPsshElement) {
      return null;
    } else if (uuid != null) {
      return new SchemeData(uuid, MimeTypes.VIDEO_MP4, data, requiresSecureDecoder);
    } else {
      Log.w(TAG, "Skipped unsupported ContentProtection element");
      return null;
    }
}

なお、先程も書いたとおり、既存ソースの処理を真似してなんとか動くようにしたという状態なので、詳しくは理解していません。
くれぐれも自己責任でお願いします。

確信が欲しいなぁ・・・。

4
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3