Bug 1350279 - try other codecs when first one failed to create. r?esawin
Video fails to play on Sony Z3C when the media server is in a state that no hardware codec can be created unless reboot. Fallback to software codec when that happens to workaround the issue.
MozReview-Commit-ID: AaRIw7KPaF3
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
@@ -316,16 +316,17 @@ import java.util.concurrent.ConcurrentLi
if (mStopped) {
return;
}
mStopped = true;
reset();
}
}
+ private String mName;
private volatile ICodecCallbacks mCallbacks;
private AsyncCodec mCodec;
private InputProcessor mInputProcessor;
private OutputProcessor mOutputProcessor;
private SamplePool mSamplePool;
// Value will be updated after configure called.
private volatile boolean mIsAdaptivePlaybackSupported = false;
@@ -357,26 +358,19 @@ import java.util.concurrent.ConcurrentLi
if (mCodec != null) {
if (DEBUG) { Log.d(LOGTAG, "release existing codec: " + mCodec); }
releaseCodec();
}
if (DEBUG) { Log.d(LOGTAG, "configure " + this); }
- MediaFormat fmt = format.asFormat();
- String codecName = getCodecForFormat(fmt, flags == MediaCodec.CONFIGURE_FLAG_ENCODE ? true : false);
- if (codecName == null) {
- Log.e(LOGTAG, "FAIL: cannot find codec");
- return false;
- }
-
try {
- AsyncCodec codec = AsyncCodecFactory.create(codecName);
-
+ MediaFormat fmt = format.asFormat();
+ AsyncCodec codec = createCodecForFormat(fmt, flags == MediaCodec.CONFIGURE_FLAG_ENCODE ? true : false);
MediaCrypto crypto = RemoteMediaDrmBridgeStub.getMediaCrypto(drmStubId);
if (DEBUG) {
boolean hasCrypto = crypto != null;
Log.d(LOGTAG, "configure mediacodec with crypto(" + hasCrypto + ") / Id :" + drmStubId);
}
codec.setCallbacks(new Callbacks(), null);
@@ -392,22 +386,21 @@ import java.util.concurrent.ConcurrentLi
fmt.setInteger(MediaFormat.KEY_MAX_HEIGHT, 1080);
}
}
codec.configure(fmt, surface, crypto, flags);
mCodec = codec;
mInputProcessor = new InputProcessor();
mOutputProcessor = new OutputProcessor(renderToSurface);
- mSamplePool = new SamplePool(codecName, renderToSurface);
+ mSamplePool = new SamplePool(mName, renderToSurface);
if (DEBUG) { Log.d(LOGTAG, codec.toString() + " created. Render to surface?" + renderToSurface); }
return true;
} catch (Exception e) {
- Log.e(LOGTAG, "FAIL: cannot create codec -- " + codecName);
- e.printStackTrace();
+ Log.e(LOGTAG, "codec creation error", e);
return false;
}
}
@Override
public synchronized boolean isAdaptivePlaybackSupported() {
return mIsAdaptivePlaybackSupported;
}
@@ -420,38 +413,44 @@ import java.util.concurrent.ConcurrentLi
mCodec.release();
} catch (Exception e) {
reportError(Error.FATAL, e);
}
mCodec = null;
}
- private String getCodecForFormat(MediaFormat format, boolean isEncoder) {
+ private AsyncCodec createCodecForFormat(MediaFormat format, boolean isEncoder) throws IOException {
String mime = format.getString(MediaFormat.KEY_MIME);
- if (mime == null) {
- return null;
+ if (mime == null || mime.isEmpty()) {
+ throw new IllegalArgumentException("invalid MIME type: " + mime);
}
+
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
if (info.isEncoder() == !isEncoder) {
continue;
}
+
String[] types = info.getSupportedTypes();
for (String t : types) {
- if (t.equalsIgnoreCase(mime)) {
- return info.getName();
+ if (!t.equalsIgnoreCase(mime)) {
+ continue;
+ }
+ try {
+ AsyncCodec codec = AsyncCodecFactory.create(info.getName());
+ mName = info.getName();
+ return codec;
+ } catch (IllegalArgumentException e) {
+ Log.w(LOGTAG, "unable to create " + info.getName() + ". Try next codec.");
}
}
}
- return null;
- // TODO: API 21+ is simpler.
- //static MediaCodecList sCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
- //return sCodecList.findDecoderForFormat(format);
+ throw new RuntimeException("cannot create codec for " + mime);
}
@Override
public synchronized void start() throws RemoteException {
if (DEBUG) { Log.d(LOGTAG, "start " + this); }
mInputProcessor.start();
mOutputProcessor.start();
try {