Bug 1789846 - Using Stride and Height values from MediaCodec instead of assuming stride and height values. r=jolin,geckoview-reviewers,owlish

Differential Revision: https://phabricator.services.mozilla.com/D159130
This commit is contained in:
Daniel Baker 2022-10-13 20:15:04 +00:00
Родитель 4d1c3500c5
Коммит 78fe69ccca
8 изменённых файлов: 74 добавлений и 9 удалений

Просмотреть файл

@ -170,14 +170,21 @@ RefPtr<MediaDataEncoder::EncodePromise> AndroidDataEncoder<ConfigType>::Encode(
} }
static jni::ByteBuffer::LocalRef ConvertI420ToNV12Buffer( static jni::ByteBuffer::LocalRef ConvertI420ToNV12Buffer(
RefPtr<const VideoData> aSample, RefPtr<MediaByteBuffer>& aYUVBuffer) { RefPtr<const VideoData> aSample, RefPtr<MediaByteBuffer>& aYUVBuffer,
int aStride, int aYPlaneHeight) {
const layers::PlanarYCbCrImage* image = aSample->mImage->AsPlanarYCbCrImage(); const layers::PlanarYCbCrImage* image = aSample->mImage->AsPlanarYCbCrImage();
MOZ_ASSERT(image); MOZ_ASSERT(image);
const layers::PlanarYCbCrData* yuv = image->GetData(); const layers::PlanarYCbCrData* yuv = image->GetData();
auto ySize = yuv->YDataSize(); auto ySize = yuv->YDataSize();
auto cbcrSize = yuv->CbCrDataSize(); auto cbcrSize = yuv->CbCrDataSize();
size_t yLength = yuv->mYStride * ySize.height; // If we have a stride or height passed in from the Codec we need to use
size_t length = yLength + (yuv->mCbCrStride * cbcrSize.height * 2); // those.
auto yStride = aStride != 0 ? aStride : yuv->mYStride;
auto height = aYPlaneHeight != 0 ? aYPlaneHeight : ySize.height;
size_t yLength = yStride * height;
size_t length =
yLength + yStride * (cbcrSize.height - 1) + cbcrSize.width * 2;
if (!aYUVBuffer || aYUVBuffer->Capacity() < length) { if (!aYUVBuffer || aYUVBuffer->Capacity() < length) {
aYUVBuffer = MakeRefPtr<MediaByteBuffer>(length); aYUVBuffer = MakeRefPtr<MediaByteBuffer>(length);
aYUVBuffer->SetLength(length); aYUVBuffer->SetLength(length);
@ -187,9 +194,9 @@ static jni::ByteBuffer::LocalRef ConvertI420ToNV12Buffer(
if (libyuv::I420ToNV12(yuv->mYChannel, yuv->mYStride, yuv->mCbChannel, if (libyuv::I420ToNV12(yuv->mYChannel, yuv->mYStride, yuv->mCbChannel,
yuv->mCbCrStride, yuv->mCrChannel, yuv->mCbCrStride, yuv->mCbCrStride, yuv->mCrChannel, yuv->mCbCrStride,
aYUVBuffer->Elements(), yuv->mYStride, aYUVBuffer->Elements(), yStride,
aYUVBuffer->Elements() + yLength, yuv->mCbCrStride * 2, aYUVBuffer->Elements() + yLength, yStride, ySize.width,
ySize.width, ySize.height) != 0) { ySize.height) != 0) {
return nullptr; return nullptr;
} }
@ -206,8 +213,11 @@ AndroidDataEncoder<ConfigType>::ProcessEncode(RefPtr<const MediaData> aSample) {
RefPtr<const VideoData> sample(aSample->As<const VideoData>()); RefPtr<const VideoData> sample(aSample->As<const VideoData>());
MOZ_ASSERT(sample); MOZ_ASSERT(sample);
jni::ByteBuffer::LocalRef buffer = // Bug 1789846: Check with the Encoder if MediaCodec has a stride or height
ConvertI420ToNV12Buffer(sample, mYUVBuffer); // value to use.
jni::ByteBuffer::LocalRef buffer = ConvertI420ToNV12Buffer(
sample, mYUVBuffer, mJavaEncoder->GetInputFormatStride(),
mJavaEncoder->GetInputFormatYPlaneHeight());
if (!buffer) { if (!buffer) {
return EncodePromise::CreateAndReject(NS_ERROR_ILLEGAL_INPUT, __func__); return EncodePromise::CreateAndReject(NS_ERROR_ILLEGAL_INPUT, __func__);
} }

Просмотреть файл

@ -14,7 +14,7 @@ import org.mozilla.gecko.media.SampleBuffer;
interface ICodec { interface ICodec {
void setCallbacks(in ICodecCallbacks callbacks); void setCallbacks(in ICodecCallbacks callbacks);
boolean configure(in FormatParam format, in GeckoSurface surface, in int flags, in String drmStubId); boolean configure(inout FormatParam format, in GeckoSurface surface, in int flags, in String drmStubId);
boolean isAdaptivePlaybackSupported(); boolean isAdaptivePlaybackSupported();
boolean isHardwareAccelerated(); boolean isHardwareAccelerated();
boolean isTunneledPlaybackSupported(); boolean isTunneledPlaybackSupported();

Просмотреть файл

@ -46,6 +46,8 @@ public interface AsyncCodec {
public abstract ByteBuffer getInputBuffer(int index); public abstract ByteBuffer getInputBuffer(int index);
public abstract MediaFormat getInputFormat();
public abstract ByteBuffer getOutputBuffer(int index); public abstract ByteBuffer getOutputBuffer(int index);
public abstract void queueInputBuffer( public abstract void queueInputBuffer(

Просмотреть файл

@ -427,6 +427,19 @@ import org.mozilla.gecko.gfx.GeckoSurface;
} }
mIsHardwareAccelerated = !name.startsWith(SW_CODEC_PREFIX); mIsHardwareAccelerated = !name.startsWith(SW_CODEC_PREFIX);
mCodec = codec; mCodec = codec;
// Bug 1789846: Check if the Codec provides stride or height values to use.
if (flags == MediaCodec.CONFIGURE_FLAG_ENCODE && fmt.containsKey(MediaFormat.KEY_WIDTH)) {
final MediaFormat inputFormat = mCodec.getInputFormat();
if (inputFormat != null) {
if (inputFormat.containsKey(MediaFormat.KEY_STRIDE)) {
fmt.setInteger(MediaFormat.KEY_STRIDE, inputFormat.getInteger(MediaFormat.KEY_STRIDE));
}
if (inputFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
fmt.setInteger(
MediaFormat.KEY_SLICE_HEIGHT, inputFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT));
}
}
}
mInputProcessor = new InputProcessor(); mInputProcessor = new InputProcessor();
final boolean renderToSurface = surface != null; final boolean renderToSurface = surface != null;
mOutputProcessor = new OutputProcessor(renderToSurface); mOutputProcessor = new OutputProcessor(renderToSurface);

Просмотреть файл

@ -132,6 +132,22 @@ public final class CodecProxy {
} }
} }
@WrapForJNI
public int GetInputFormatStride() {
if (mFormat.asFormat().containsKey(MediaFormat.KEY_STRIDE)) {
return mFormat.asFormat().getInteger(MediaFormat.KEY_STRIDE);
}
return 0;
}
@WrapForJNI
public int GetInputFormatYPlaneHeight() {
if (mFormat.asFormat().containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
return mFormat.asFormat().getInteger(MediaFormat.KEY_SLICE_HEIGHT);
}
return 0;
}
@WrapForJNI @WrapForJNI
public static CodecProxy create( public static CodecProxy create(
final boolean isEncoder, final boolean isEncoder,

Просмотреть файл

@ -24,6 +24,8 @@ import java.nio.ByteBuffer;
* <li>{@link MediaFormat#KEY_COLOR_FORMAT} * <li>{@link MediaFormat#KEY_COLOR_FORMAT}
* <li>{@link MediaFormat#KEY_FRAME_RATE} * <li>{@link MediaFormat#KEY_FRAME_RATE}
* <li>{@link MediaFormat#KEY_I_FRAME_INTERVAL} * <li>{@link MediaFormat#KEY_I_FRAME_INTERVAL}
* <li>{@link MediaFormat#KEY_STRIDE}
* <li>{@link MediaFormat#KEY_SLICE_HEIGHT}
* <li>"csd-0" * <li>"csd-0"
* <li>"csd-1" * <li>"csd-1"
* </ul> * </ul>
@ -110,6 +112,12 @@ public final class FormatParam implements Parcelable {
mFormat.setInteger( mFormat.setInteger(
MediaFormat.KEY_I_FRAME_INTERVAL, bundle.getInt(MediaFormat.KEY_I_FRAME_INTERVAL)); MediaFormat.KEY_I_FRAME_INTERVAL, bundle.getInt(MediaFormat.KEY_I_FRAME_INTERVAL));
} }
if (bundle.containsKey(MediaFormat.KEY_STRIDE)) {
mFormat.setInteger(MediaFormat.KEY_STRIDE, bundle.getInt(MediaFormat.KEY_STRIDE));
}
if (bundle.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
mFormat.setInteger(MediaFormat.KEY_SLICE_HEIGHT, bundle.getInt(MediaFormat.KEY_SLICE_HEIGHT));
}
} }
@Override @Override
@ -159,6 +167,12 @@ public final class FormatParam implements Parcelable {
bundle.putInt( bundle.putInt(
MediaFormat.KEY_I_FRAME_INTERVAL, mFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL)); MediaFormat.KEY_I_FRAME_INTERVAL, mFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL));
} }
if (mFormat.containsKey(MediaFormat.KEY_STRIDE)) {
bundle.putInt(MediaFormat.KEY_STRIDE, mFormat.getInteger(MediaFormat.KEY_STRIDE));
}
if (mFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
bundle.putInt(MediaFormat.KEY_SLICE_HEIGHT, mFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT));
}
return bundle; return bundle;
} }
} }

Просмотреть файл

@ -436,6 +436,11 @@ final class JellyBeanAsyncCodec implements AsyncCodec {
return mOutputBuffers[index]; return mOutputBuffers[index];
} }
@Override
public MediaFormat getInputFormat() {
return null;
}
@Override @Override
public void flush() { public void flush() {
assertCallbacks(); assertCallbacks();

Просмотреть файл

@ -213,6 +213,11 @@ import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
return mCodec.getOutputBuffer(index); return mCodec.getOutputBuffer(index);
} }
@Override
public MediaFormat getInputFormat() {
return mCodec.getInputFormat();
}
@Override @Override
public void queueInputBuffer( public void queueInputBuffer(
final int index, final int index,