如何实现包装 SubtitleDecoderFactory.DEFAULT 的自定义 SubtitleDecoderFactory,这是一个常量实例

How to implement a custom SubtitleDecoderFactory which wraps SubtitleDecoderFactory.DEFAULT, which is a constant instance

我正在学习 Exoplayer,在 https://github.com/google/ExoPlayer/issues/4657 (at the end of the post by erdemguven commented on 24 Aug 2018) regarding creating a wrapper SubtitleDecoderFactory which wraps SubtitleDecoderFactory.DEFAULT (at https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderFactory.java 找到了一个 post。

在Whosebug的另一个post中,我问了一个关于SubtitleDecoderFactory.DEFAULT的问题,从中我了解到SubtitleDecoderFactory.DEFAULT是一个常量实例。 (在

所以我的问题是:

  1. 是否需要包装一个常量实例,因为常量实例可以在程序的任何地方看到和引用?

  2. 如果需要包装这个常量实例SubtitleDecoderFactory.DEFAULT,代码会怎样?

这是基本接口 SubtitleDecoderFactory(在 https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderFactory.java):

public interface SubtitleDecoderFactory {


  boolean supportsFormat(Format format);


  SubtitleDecoder createDecoder(Format format);


  SubtitleDecoderFactory DEFAULT =
      new SubtitleDecoderFactory() {

        @Override
        public boolean supportsFormat(Format format) {
          @Nullable String mimeType = format.sampleMimeType;
          return MimeTypes.TEXT_VTT.equals(mimeType)
              || MimeTypes.TEXT_SSA.equals(mimeType)
              || MimeTypes.APPLICATION_TTML.equals(mimeType)
              || MimeTypes.APPLICATION_MP4VTT.equals(mimeType)
              || MimeTypes.APPLICATION_SUBRIP.equals(mimeType)
              || MimeTypes.APPLICATION_TX3G.equals(mimeType)
              || MimeTypes.APPLICATION_CEA608.equals(mimeType)
              || MimeTypes.APPLICATION_MP4CEA608.equals(mimeType)
              || MimeTypes.APPLICATION_CEA708.equals(mimeType)
              || MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)
              || MimeTypes.APPLICATION_PGS.equals(mimeType);
        }

        @Override
        public SubtitleDecoder createDecoder(Format format) {
          @Nullable String mimeType = format.sampleMimeType;
          if (mimeType != null) {
            switch (mimeType) {
              case MimeTypes.TEXT_VTT:
                return new WebvttDecoder();
              case MimeTypes.TEXT_SSA:
                return new SsaDecoder(format.initializationData);
              case MimeTypes.APPLICATION_MP4VTT:
                return new Mp4WebvttDecoder();
              case MimeTypes.APPLICATION_TTML:
                return new TtmlDecoder();
              case MimeTypes.APPLICATION_SUBRIP:
                return new SubripDecoder();
              case MimeTypes.APPLICATION_TX3G:
                return new Tx3gDecoder(format.initializationData);
              case MimeTypes.APPLICATION_CEA608:
              case MimeTypes.APPLICATION_MP4CEA608:
                return new Cea608Decoder(mimeType, format.accessibilityChannel);
              case MimeTypes.APPLICATION_CEA708:
                return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
              case MimeTypes.APPLICATION_DVBSUBS:
                return new DvbDecoder(format.initializationData);
              case MimeTypes.APPLICATION_PGS:
                return new PgsDecoder();
              default:
                break;
            }
          }
          throw new IllegalArgumentException(
              "Attempted to create decoder for unsupported MIME type: " + mimeType);
        }
      };
}

我的自定义 SubtitleDecoderFactory 看起来像:

public class mSubtitleDecoderFactory implements SubtitleDecoderFactory{

    @Override
    public boolean supportsFormat(Format format) {
        @Nullable String mimeType = format.sampleMimeType;
        return MimeTypes.TEXT_VTT.equals(mimeType)
                || MimeTypes.TEXT_SSA.equals(mimeType)
                || MimeTypes.APPLICATION_TTML.equals(mimeType)
                || MimeTypes.APPLICATION_MP4VTT.equals(mimeType)
                || MimeTypes.APPLICATION_SUBRIP.equals(mimeType)
                || MimeTypes.APPLICATION_TX3G.equals(mimeType)
                || MimeTypes.APPLICATION_CEA608.equals(mimeType)
                || MimeTypes.APPLICATION_MP4CEA608.equals(mimeType)
                || MimeTypes.APPLICATION_CEA708.equals(mimeType)
                || MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)
                || MimeTypes.APPLICATION_PGS.equals(mimeType);
    }

    @Override
    public SubtitleDecoder createDecoder(Format format){

        @Nullable String mimeType = format.sampleMimeType;
        if (mimeType != null) {
            switch (mimeType) {
                case MimeTypes.TEXT_VTT:
                    return new WebvttDecoder();
                case MimeTypes.TEXT_SSA:
                    return new SsaDecoder(format.initializationData);
                case MimeTypes.APPLICATION_MP4VTT:
                    return new Mp4WebvttDecoder();
                case MimeTypes.APPLICATION_TTML:
                    return new TtmlDecoder();
                case MimeTypes.APPLICATION_SUBRIP:
                    return new SubripDecoder();
                case MimeTypes.APPLICATION_TX3G:
                    return new Tx3gDecoder(format.initializationData);
                case MimeTypes.APPLICATION_CEA608:
                case MimeTypes.APPLICATION_MP4CEA608:
                    return new Cea608Decoder(mimeType, format.accessibilityChannel);
                case MimeTypes.APPLICATION_CEA708:
                    return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
                case MimeTypes.APPLICATION_DVBSUBS:
                    return new DvbDecoder(format.initializationData);
                case MimeTypes.APPLICATION_PGS:
                    return new PgsDecoder();
                default:
                    break;
            }
        }
        throw new IllegalArgumentException(
                "Attempted to create decoder for unsupported MIME type: " + mimeType);
    };


};

基本上它覆盖了两个抽象方法 "boolean supportsFormat(Format format)" 和 "SubtitleDecoder createDecoder(Format format)" 在基接口 SubtitleDecoderFactory

中声明

但是要将 SubtitleDecoderFactory.DEFAULT 作为参数放在何处才能进行包装?

提前感谢您的帮助。

据我了解 https://github.com/google/ExoPlayer/issues/4657#issuecomment-415739157,对于您的情况,您需要创建一个具有以下行为的 SubtitleDecoderFactory 实例:

supportsFormat 调用委托给 SubtitleDecoderFactory.DEFAULT

createDecoder 调用使用 SubtitleDecoderFactory.DEFAULT 创建 SubtitleDecoder 实例并将其包装到另一个 SubtitleDecoder 实例(我们将使用匿名 class ),它将除 dequeueOutputBuffer 之外的所有方法委托给包装实例,并且对于 dequeueOutputBuffer 它将使用您的自定义逻辑。

您的代码可能如下所示:

public class mSubtitleDecoderFactory implements SubtitleDecoderFactory{

    @Override
    public boolean supportsFormat(Format format) {
        return SubtitleDecoderFactory.DEFAULT.supportsFormat(format);
    }

    @Override
    public SubtitleDecoder createDecoder(Format format){
        SubtitleDecoder wrapped = SubtitleDecoderFactory.DEFAULT.createDecoder(format);
        SubtitleDecoder wrapper = new SubtitleDecoder() {

            @Override
            O dequeueOutputBuffer() throws E {
                O resultFromWrapped = wrapped.dequeueOutputBuffer()
                // Do what you want with resultFromWrapped and return it modified
            }

            @Override
            String getName() {
                return wrapped.getName();
            }

            @Override
            void queueInputBuffer(I inputBuffer) throws E {
                wrapped.queueInputBuffer(inputBuffer);
            }

            // Delegate all other methods

        };
        return wrapper
    }

}