зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
4d1c3500c5
Коммит
78fe69ccca
|
@ -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,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче