mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1014614 - Use Android MediaCodec for decoding H264 and AAC in MP4 r=cpearce,edwin,snorp
--HG-- extra : rebase_source : 5f104f687b6a68d4d4100abf8a8a28039fbb324d extra : histedit_source : 6f609ebacd51fffcdcfec92c99329b758c6fdbce
This commit is contained in:
parent
01348c1f39
commit
d1679cdb9c
@ -5301,8 +5301,15 @@ fi;
|
|||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
dnl = Built-in fragmented MP4 support.
|
dnl = Built-in fragmented MP4 support.
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
|
||||||
|
if test "$OS_TARGET" = Android; then
|
||||||
|
MOZ_FMP4=1
|
||||||
|
fi
|
||||||
|
|
||||||
if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG" -o -n "$MOZ_APPLEMEDIA"; then
|
if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG" -o -n "$MOZ_APPLEMEDIA"; then
|
||||||
dnl Enable fragmented MP4 parser on platforms with decoder support.
|
dnl Enable fragmented MP4 parser on Windows by default.
|
||||||
|
dnl We will also need to enable it on other platforms as we implement
|
||||||
|
dnl platform decoder support there too.
|
||||||
MOZ_FMP4=1
|
MOZ_FMP4=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#ifdef MOZ_APPLEMEDIA
|
#ifdef MOZ_APPLEMEDIA
|
||||||
#include "apple/AppleDecoderModule.h"
|
#include "apple/AppleDecoderModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
#include "AndroidBridge.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
@ -167,6 +170,10 @@ HavePlatformMPEGDecoders()
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// We have H.264/AAC platform decoders on Windows Vista and up.
|
// We have H.264/AAC platform decoders on Windows Vista and up.
|
||||||
IsVistaOrLater() ||
|
IsVistaOrLater() ||
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
// We need android.media.MediaCodec which exists in API level 16 and higher.
|
||||||
|
(AndroidBridge::Bridge()->GetAPIVersion() >= 16) ||
|
||||||
#endif
|
#endif
|
||||||
IsFFmpegAvailable() ||
|
IsFFmpegAvailable() ||
|
||||||
IsAppleAvailable() ||
|
IsAppleAvailable() ||
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#ifdef MOZ_GONK_MEDIACODEC
|
#ifdef MOZ_GONK_MEDIACODEC
|
||||||
#include "GonkDecoderModule.h"
|
#include "GonkDecoderModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
#include "AndroidDecoderModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#ifdef MOZ_EME
|
#ifdef MOZ_EME
|
||||||
@ -33,6 +36,8 @@ extern PlatformDecoderModule* CreateBlankDecoderModule();
|
|||||||
bool PlatformDecoderModule::sUseBlankDecoder = false;
|
bool PlatformDecoderModule::sUseBlankDecoder = false;
|
||||||
bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
|
bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
|
||||||
bool PlatformDecoderModule::sGonkDecoderEnabled = false;
|
bool PlatformDecoderModule::sGonkDecoderEnabled = false;
|
||||||
|
bool PlatformDecoderModule::sAndroidMCDecoderEnabled = false;
|
||||||
|
bool PlatformDecoderModule::sAndroidMCDecoderPreferred = false;
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void
|
void
|
||||||
@ -49,10 +54,18 @@ PlatformDecoderModule::Init()
|
|||||||
"media.fragmented-mp4.use-blank-decoder");
|
"media.fragmented-mp4.use-blank-decoder");
|
||||||
Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
|
Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
|
||||||
"media.fragmented-mp4.ffmpeg.enabled", false);
|
"media.fragmented-mp4.ffmpeg.enabled", false);
|
||||||
|
|
||||||
#ifdef MOZ_GONK_MEDIACODEC
|
#ifdef MOZ_GONK_MEDIACODEC
|
||||||
Preferences::AddBoolVarCache(&sGonkDecoderEnabled,
|
Preferences::AddBoolVarCache(&sGonkDecoderEnabled,
|
||||||
"media.fragmented-mp4.gonk.enabled", false);
|
"media.fragmented-mp4.gonk.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
Preferences::AddBoolVarCache(&sAndroidMCDecoderEnabled,
|
||||||
|
"media.fragmented-mp4.android-media-codec.enabled", false);
|
||||||
|
Preferences::AddBoolVarCache(&sAndroidMCDecoderPreferred,
|
||||||
|
"media.fragmented-mp4.android-media-codec.preferred", false);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
WMFDecoderModule::Init();
|
WMFDecoderModule::Init();
|
||||||
#endif
|
#endif
|
||||||
@ -122,6 +135,11 @@ PlatformDecoderModule::Create()
|
|||||||
// Note: This runs on the decode thread.
|
// Note: This runs on the decode thread.
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled){
|
||||||
|
return new AndroidDecoderModule();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (sUseBlankDecoder) {
|
if (sUseBlankDecoder) {
|
||||||
return CreateBlankDecoderModule();
|
return CreateBlankDecoderModule();
|
||||||
}
|
}
|
||||||
@ -149,6 +167,11 @@ PlatformDecoderModule::Create()
|
|||||||
if (sGonkDecoderEnabled) {
|
if (sGonkDecoderEnabled) {
|
||||||
return new GonkDecoderModule();
|
return new GonkDecoderModule();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
if(sAndroidMCDecoderEnabled){
|
||||||
|
return new AndroidDecoderModule();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,8 @@ protected:
|
|||||||
static bool sUseBlankDecoder;
|
static bool sUseBlankDecoder;
|
||||||
static bool sFFmpegDecoderEnabled;
|
static bool sFFmpegDecoderEnabled;
|
||||||
static bool sGonkDecoderEnabled;
|
static bool sGonkDecoderEnabled;
|
||||||
|
static bool sAndroidMCDecoderPreferred;
|
||||||
|
static bool sAndroidMCDecoderEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A callback used by MediaDataDecoder to return output/errors to the
|
// A callback used by MediaDataDecoder to return output/errors to the
|
||||||
|
494
content/media/fmp4/android/AndroidDecoderModule.cpp
Normal file
494
content/media/fmp4/android/AndroidDecoderModule.cpp
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "AndroidDecoderModule.h"
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
#include "GeneratedJNIWrappers.h"
|
||||||
|
#include "GeneratedSDKWrappers.h"
|
||||||
|
#include "AndroidBridge.h"
|
||||||
|
#include "MediaTaskQueue.h"
|
||||||
|
#include "SharedThreadPool.h"
|
||||||
|
#include "TexturePoolOGL.h"
|
||||||
|
#include "GLImages.h"
|
||||||
|
|
||||||
|
#include "MediaData.h"
|
||||||
|
|
||||||
|
#include "mp4_demuxer/AnnexB.h"
|
||||||
|
#include "mp4_demuxer/DecoderData.h"
|
||||||
|
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::gl;
|
||||||
|
using namespace mozilla::widget::android;
|
||||||
|
|
||||||
|
static MediaCodec* CreateDecoder(JNIEnv* aEnv, const char* aMimeType)
|
||||||
|
{
|
||||||
|
if (!aMimeType) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString mimeType;
|
||||||
|
mimeType.AssignASCII(aMimeType);
|
||||||
|
|
||||||
|
jobject decoder = MediaCodec::CreateDecoderByType(mimeType);
|
||||||
|
|
||||||
|
return new MediaCodec(decoder, aEnv);
|
||||||
|
}
|
||||||
|
|
||||||
|
class VideoDataDecoder : public MediaCodecDataDecoder {
|
||||||
|
public:
|
||||||
|
VideoDataDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
MediaFormat* aFormat, MediaDataDecoderCallback* aCallback,
|
||||||
|
layers::ImageContainer* aImageContainer)
|
||||||
|
: MediaCodecDataDecoder(MediaData::Type::VIDEO_FRAME, aConfig.mime_type, aFormat, aCallback)
|
||||||
|
, mImageContainer(aImageContainer)
|
||||||
|
, mConfig(aConfig)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult Init() MOZ_OVERRIDE {
|
||||||
|
mSurfaceTexture = AndroidSurfaceTexture::Create();
|
||||||
|
if (!mSurfaceTexture) {
|
||||||
|
printf_stderr("Failed to create SurfaceTexture for video decode\n");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InitDecoder(mSurfaceTexture->JavaSurface());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE {
|
||||||
|
mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b);
|
||||||
|
return MediaCodecDataDecoder::Input(aSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsresult PostOutput(BufferInfo* aInfo, Microseconds aDuration) MOZ_OVERRIDE {
|
||||||
|
VideoInfo videoInfo;
|
||||||
|
videoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height);
|
||||||
|
|
||||||
|
bool isSync = false;
|
||||||
|
if (MediaCodec::getBUFFER_FLAG_SYNC_FRAME() & aInfo->getFlags()) {
|
||||||
|
isSync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<layers::Image> img = mImageContainer->CreateImage(ImageFormat::SURFACE_TEXTURE);
|
||||||
|
layers::SurfaceTextureImage::Data data;
|
||||||
|
data.mSurfTex = mSurfaceTexture.get();
|
||||||
|
data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height);
|
||||||
|
data.mInverted = true;
|
||||||
|
|
||||||
|
layers::SurfaceTextureImage* typedImg = static_cast<layers::SurfaceTextureImage*>(img.get());
|
||||||
|
typedImg->SetData(data);
|
||||||
|
|
||||||
|
mCallback->Output(VideoData::CreateFromImage(videoInfo, mImageContainer, aInfo->getOffset(),
|
||||||
|
aInfo->getPresentationTimeUs(),
|
||||||
|
aDuration,
|
||||||
|
img, isSync,
|
||||||
|
aInfo->getPresentationTimeUs(),
|
||||||
|
gfx::IntRect(0, 0,
|
||||||
|
mConfig.display_width,
|
||||||
|
mConfig.display_height)));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
layers::ImageContainer* mImageContainer;
|
||||||
|
const mp4_demuxer::VideoDecoderConfig& mConfig;
|
||||||
|
nsRefPtr<AndroidSurfaceTexture> mSurfaceTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioDataDecoder : public MediaCodecDataDecoder {
|
||||||
|
public:
|
||||||
|
AudioDataDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||||
|
MediaFormat* aFormat, MediaDataDecoderCallback* aCallback)
|
||||||
|
: MediaCodecDataDecoder(MediaData::Type::AUDIO_SAMPLES, aConfig.mime_type, aFormat, aCallback)
|
||||||
|
, mConfig(aConfig)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mConfig.bits_per_sample == 16, "We only support 16-bit audio");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult Output(BufferInfo* aInfo, void* aBuffer, Microseconds aDuration) {
|
||||||
|
// The output on Android is always 16-bit signed
|
||||||
|
|
||||||
|
uint32_t numChannels = mConfig.channel_count;
|
||||||
|
uint32_t numFrames = (aInfo->getSize() / numChannels) / 2;
|
||||||
|
|
||||||
|
AudioDataValue* audio = new AudioDataValue[aInfo->getSize()];
|
||||||
|
PodCopy(audio, static_cast<AudioDataValue*>(aBuffer), aInfo->getSize());
|
||||||
|
|
||||||
|
mCallback->Output(new AudioData(aInfo->getOffset(), aInfo->getPresentationTimeUs(),
|
||||||
|
aDuration,
|
||||||
|
numFrames,
|
||||||
|
audio,
|
||||||
|
numChannels,
|
||||||
|
mConfig.samples_per_second));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const mp4_demuxer::AudioDecoderConfig& mConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool AndroidDecoderModule::SupportsAudioMimeType(const char* aMimeType) {
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
MediaCodec* decoder = CreateDecoder(env, aMimeType);
|
||||||
|
bool supports = (decoder != nullptr);
|
||||||
|
delete decoder;
|
||||||
|
return supports;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<MediaDataDecoder>
|
||||||
|
AndroidDecoderModule::CreateH264Decoder(
|
||||||
|
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
layers::LayersBackend aLayersBackend,
|
||||||
|
layers::ImageContainer* aImageContainer,
|
||||||
|
MediaTaskQueue* aVideoTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
|
{
|
||||||
|
nsAutoString mimeType;
|
||||||
|
mimeType.AssignASCII(aConfig.mime_type);
|
||||||
|
|
||||||
|
jobject jFormat = MediaFormat::CreateVideoFormat(mimeType,
|
||||||
|
aConfig.display_width,
|
||||||
|
aConfig.display_height);
|
||||||
|
|
||||||
|
if (!jFormat) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaFormat* format = MediaFormat::Wrap(jFormat);
|
||||||
|
|
||||||
|
if (!format) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<MediaDataDecoder> decoder =
|
||||||
|
new VideoDataDecoder(aConfig, format, aCallback, aImageContainer);
|
||||||
|
|
||||||
|
return decoder.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<MediaDataDecoder>
|
||||||
|
AndroidDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||||
|
MediaTaskQueue* aAudioTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
|
{
|
||||||
|
|
||||||
|
nsAutoString mimeType;
|
||||||
|
mimeType.AssignASCII(aConfig.mime_type);
|
||||||
|
|
||||||
|
jobject jFormat = MediaFormat::CreateAudioFormat(mimeType,
|
||||||
|
aConfig.samples_per_second,
|
||||||
|
aConfig.channel_count);
|
||||||
|
|
||||||
|
if (jFormat == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
MediaFormat* format = MediaFormat::Wrap(jFormat);
|
||||||
|
|
||||||
|
if(format == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
|
||||||
|
if (!format->GetByteBuffer(NS_LITERAL_STRING("csd-0"))) {
|
||||||
|
uint8_t* csd0 = new uint8_t[2];
|
||||||
|
|
||||||
|
csd0[0] = aConfig.audio_specific_config[0];
|
||||||
|
csd0[1] = aConfig.audio_specific_config[1];
|
||||||
|
|
||||||
|
jobject buffer = env->NewDirectByteBuffer(csd0, 2);
|
||||||
|
format->SetByteBuffer(NS_LITERAL_STRING("csd-0"), buffer);
|
||||||
|
|
||||||
|
env->DeleteLocalRef(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mimeType.EqualsLiteral("audio/mp4a-latm")) {
|
||||||
|
format->SetInteger(NS_LITERAL_STRING("is-adts"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<MediaDataDecoder> decoder =
|
||||||
|
new AudioDataDecoder(aConfig, format, aCallback);
|
||||||
|
|
||||||
|
return decoder.forget();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult AndroidDecoderModule::Shutdown()
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
|
||||||
|
const char* aMimeType,
|
||||||
|
MediaFormat* aFormat,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
|
: mType(aType)
|
||||||
|
, mMimeType(strdup(aMimeType))
|
||||||
|
, mFormat(aFormat)
|
||||||
|
, mCallback(aCallback)
|
||||||
|
, mInputBuffers(nullptr)
|
||||||
|
, mOutputBuffers(nullptr)
|
||||||
|
, mMonitor("MediaCodecDataDecoder::mMonitor")
|
||||||
|
, mDraining(false)
|
||||||
|
, mStopping(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaCodecDataDecoder::~MediaCodecDataDecoder()
|
||||||
|
{
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
|
||||||
|
Shutdown();
|
||||||
|
|
||||||
|
if (mInputBuffers) {
|
||||||
|
env->DeleteGlobalRef(mInputBuffers);
|
||||||
|
mInputBuffers = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOutputBuffers) {
|
||||||
|
env->DeleteGlobalRef(mOutputBuffers);
|
||||||
|
mOutputBuffers = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::Init()
|
||||||
|
{
|
||||||
|
return InitDecoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::InitDecoder(jobject aSurface)
|
||||||
|
{
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
mDecoder = CreateDecoder(env, mMimeType);
|
||||||
|
if (!mDecoder) {
|
||||||
|
mCallback->Error();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDecoder->Configure(mFormat->wrappedObject(), aSurface, nullptr, 0);
|
||||||
|
mDecoder->Start();
|
||||||
|
|
||||||
|
ResetInputBuffers();
|
||||||
|
ResetOutputBuffers();
|
||||||
|
|
||||||
|
NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread),
|
||||||
|
NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is in usec, so that's 10ms
|
||||||
|
#define DECODER_TIMEOUT 10000
|
||||||
|
|
||||||
|
void MediaCodecDataDecoder::DecoderLoop()
|
||||||
|
{
|
||||||
|
bool outputDone = false;
|
||||||
|
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
mp4_demuxer::MP4Sample* sample = nullptr;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
{
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
while (!mStopping && !mDraining && mQueue.empty()) {
|
||||||
|
if (mQueue.empty()) {
|
||||||
|
// We could be waiting here forever if we don't signal that we need more input
|
||||||
|
mCallback->InputExhausted();
|
||||||
|
}
|
||||||
|
lock.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mStopping) {
|
||||||
|
// Get out of the loop. This is the only exit point.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDraining) {
|
||||||
|
mDecoder->Flush();
|
||||||
|
ClearQueue();
|
||||||
|
mDraining = false;
|
||||||
|
lock.Notify();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're not stopping or draining, so try to get a sample
|
||||||
|
if (!mQueue.empty()) {
|
||||||
|
sample = mQueue.front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample) {
|
||||||
|
// We have a sample, try to feed it to the decoder
|
||||||
|
int inputIndex = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT);
|
||||||
|
if (inputIndex >= 0) {
|
||||||
|
jobject buffer = env->GetObjectArrayElement(mInputBuffers, inputIndex);
|
||||||
|
void* directBuffer = env->GetDirectBufferAddress(buffer);
|
||||||
|
|
||||||
|
// We're feeding this to the decoder, so remove it from the queue
|
||||||
|
mMonitor.Lock();
|
||||||
|
mQueue.pop();
|
||||||
|
mMonitor.Unlock();
|
||||||
|
|
||||||
|
MOZ_ASSERT(env->GetDirectBufferCapacity(buffer) >= sample->size,
|
||||||
|
"Decoder buffer is not large enough for sample");
|
||||||
|
|
||||||
|
PodCopy((uint8_t*)directBuffer, sample->data, sample->size);
|
||||||
|
|
||||||
|
mDecoder->QueueInputBuffer(inputIndex, 0, sample->size, sample->composition_timestamp, 0);
|
||||||
|
mDurations.push(sample->duration);
|
||||||
|
|
||||||
|
delete sample;
|
||||||
|
sample = nullptr;
|
||||||
|
|
||||||
|
outputDone = false;
|
||||||
|
env->DeleteLocalRef(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outputDone) {
|
||||||
|
BufferInfo bufferInfo;
|
||||||
|
|
||||||
|
int outputStatus = mDecoder->DequeueOutputBuffer(bufferInfo.wrappedObject(), DECODER_TIMEOUT);
|
||||||
|
if (outputStatus == MediaCodec::getINFO_TRY_AGAIN_LATER()) {
|
||||||
|
// We might want to call mCallback->InputExhausted() here, but there seems to be
|
||||||
|
// some possible bad interactions here with the threading
|
||||||
|
} else if (outputStatus == MediaCodec::getINFO_OUTPUT_BUFFERS_CHANGED()) {
|
||||||
|
ResetOutputBuffers();
|
||||||
|
} else if (outputStatus == MediaCodec::getINFO_OUTPUT_FORMAT_CHANGED()) {
|
||||||
|
// Don't care, we use SurfaceTexture for video
|
||||||
|
} else if (outputStatus < 0) {
|
||||||
|
printf_stderr("unknown error from decoder! %d\n", outputStatus);
|
||||||
|
mCallback->Error();
|
||||||
|
} else {
|
||||||
|
// We have a valid buffer index >= 0 here
|
||||||
|
if (bufferInfo.getFlags() & MediaCodec::getBUFFER_FLAG_END_OF_STREAM()) {
|
||||||
|
outputDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mDurations.empty(), "Should have had a duration queued");
|
||||||
|
|
||||||
|
Microseconds duration = 0;
|
||||||
|
if (!mDurations.empty()) {
|
||||||
|
duration = mDurations.front();
|
||||||
|
mDurations.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject buffer = env->GetObjectArrayElement(mOutputBuffers, outputStatus);
|
||||||
|
if (buffer) {
|
||||||
|
// The buffer will be null on Android L if we are decoding to a Surface
|
||||||
|
void* directBuffer = env->GetDirectBufferAddress(buffer);
|
||||||
|
Output(&bufferInfo, directBuffer, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Surface will be updated at this point (for video)
|
||||||
|
mDecoder->ReleaseOutputBuffer(outputStatus, true);
|
||||||
|
|
||||||
|
PostOutput(&bufferInfo, duration);
|
||||||
|
|
||||||
|
if (buffer) {
|
||||||
|
env->DeleteLocalRef(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done
|
||||||
|
mMonitor.Lock();
|
||||||
|
mStopping = false;
|
||||||
|
mMonitor.Notify();
|
||||||
|
mMonitor.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaCodecDataDecoder::ClearQueue()
|
||||||
|
{
|
||||||
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
while (!mQueue.empty()) {
|
||||||
|
delete mQueue.front();
|
||||||
|
mQueue.pop();
|
||||||
|
}
|
||||||
|
while (!mDurations.empty()) {
|
||||||
|
mDurations.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::Input(mp4_demuxer::MP4Sample* aSample) {
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
mQueue.push(aSample);
|
||||||
|
lock.NotifyAll();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaCodecDataDecoder::ResetInputBuffers()
|
||||||
|
{
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
|
||||||
|
if (mInputBuffers) {
|
||||||
|
env->DeleteGlobalRef(mInputBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
mInputBuffers = (jobjectArray) env->NewGlobalRef(mDecoder->GetInputBuffers());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaCodecDataDecoder::ResetOutputBuffers()
|
||||||
|
{
|
||||||
|
JNIEnv* env = GetJNIForThread();
|
||||||
|
|
||||||
|
if (mOutputBuffers) {
|
||||||
|
env->DeleteGlobalRef(mOutputBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
mOutputBuffers = (jobjectArray) env->NewGlobalRef(mDecoder->GetOutputBuffers());
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::Flush() {
|
||||||
|
Drain();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::Drain() {
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
mDraining = true;
|
||||||
|
lock.Notify();
|
||||||
|
|
||||||
|
while (mDraining) {
|
||||||
|
lock.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
mCallback->DrainComplete();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult MediaCodecDataDecoder::Shutdown() {
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
|
if (!mThread || mStopping) {
|
||||||
|
// Already shutdown or in the process of doing so
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mStopping = true;
|
||||||
|
lock.Notify();
|
||||||
|
|
||||||
|
while (mStopping) {
|
||||||
|
lock.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
mThread->Shutdown();
|
||||||
|
mThread = nullptr;
|
||||||
|
|
||||||
|
mDecoder->Stop();
|
||||||
|
mDecoder->Release();
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
}
|
109
content/media/fmp4/android/AndroidDecoderModule.h
Normal file
109
content/media/fmp4/android/AndroidDecoderModule.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef AndroidDecoderModule_h_
|
||||||
|
#define AndroidDecoderModule_h_
|
||||||
|
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
#include "AndroidJavaWrappers.h"
|
||||||
|
#include "AndroidSurfaceTexture.h"
|
||||||
|
|
||||||
|
#include "GeneratedSDKWrappers.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
typedef std::queue<mp4_demuxer::MP4Sample*> SampleQueue;
|
||||||
|
|
||||||
|
namespace widget {
|
||||||
|
namespace android {
|
||||||
|
class MediaCodec;
|
||||||
|
class MediaFormat;
|
||||||
|
class ByteBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MediaCodecDataDecoder;
|
||||||
|
|
||||||
|
class AndroidDecoderModule : public PlatformDecoderModule {
|
||||||
|
public:
|
||||||
|
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
|
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
layers::LayersBackend aLayersBackend,
|
||||||
|
layers::ImageContainer* aImageContainer,
|
||||||
|
MediaTaskQueue* aVideoTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
|
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||||
|
MediaTaskQueue* aAudioTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
|
||||||
|
AndroidDecoderModule() {}
|
||||||
|
virtual ~AndroidDecoderModule() {}
|
||||||
|
|
||||||
|
virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MediaCodecDataDecoder : public MediaDataDecoder {
|
||||||
|
public:
|
||||||
|
|
||||||
|
MediaCodecDataDecoder(MediaData::Type aType,
|
||||||
|
const char* aMimeType,
|
||||||
|
mozilla::widget::android::MediaFormat* aFormat,
|
||||||
|
MediaDataDecoderCallback* aCallback);
|
||||||
|
|
||||||
|
virtual ~MediaCodecDataDecoder();
|
||||||
|
|
||||||
|
virtual nsresult Init() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class AndroidDecoderModule;
|
||||||
|
|
||||||
|
MediaData::Type mType;
|
||||||
|
|
||||||
|
nsAutoPtr<char> mMimeType;
|
||||||
|
nsAutoPtr<mozilla::widget::android::MediaFormat> mFormat;
|
||||||
|
|
||||||
|
MediaDataDecoderCallback* mCallback;
|
||||||
|
|
||||||
|
nsAutoPtr<mozilla::widget::android::MediaCodec> mDecoder;
|
||||||
|
|
||||||
|
jobjectArray mInputBuffers;
|
||||||
|
jobjectArray mOutputBuffers;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> mThread;
|
||||||
|
|
||||||
|
// Only these members are protected by mMonitor.
|
||||||
|
Monitor mMonitor;
|
||||||
|
bool mDraining;
|
||||||
|
bool mStopping;
|
||||||
|
|
||||||
|
SampleQueue mQueue;
|
||||||
|
std::queue<Microseconds> mDurations;
|
||||||
|
|
||||||
|
virtual nsresult InitDecoder(jobject aSurface = nullptr);
|
||||||
|
|
||||||
|
virtual nsresult Output(mozilla::widget::android::BufferInfo* aInfo, void* aBuffer, Microseconds aDuration) { return NS_OK; }
|
||||||
|
virtual nsresult PostOutput(mozilla::widget::android::BufferInfo* aInfo, Microseconds aDuration) { return NS_OK; }
|
||||||
|
|
||||||
|
void ResetInputBuffers();
|
||||||
|
void ResetOutputBuffers();
|
||||||
|
|
||||||
|
void DecoderLoop();
|
||||||
|
virtual void ClearQueue();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namwspace mozilla
|
||||||
|
|
||||||
|
#endif
|
@ -25,7 +25,7 @@ if CONFIG['MOZ_WMF']:
|
|||||||
|
|
||||||
if CONFIG['MOZ_EME']:
|
if CONFIG['MOZ_EME']:
|
||||||
DIRS += ['eme']
|
DIRS += ['eme']
|
||||||
|
|
||||||
if CONFIG['MOZ_FFMPEG']:
|
if CONFIG['MOZ_FFMPEG']:
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'ffmpeg/FFmpegRuntimeLinker.h',
|
'ffmpeg/FFmpegRuntimeLinker.h',
|
||||||
@ -67,6 +67,14 @@ if CONFIG['ANDROID_VERSION'] >= '18'and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
|||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||||
|
EXPORTS += [
|
||||||
|
'android/AndroidDecoderModule.h',
|
||||||
|
]
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'android/AndroidDecoderModule.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
||||||
FAIL_ON_WARNINGS = True
|
FAIL_ON_WARNINGS = True
|
||||||
|
@ -560,6 +560,12 @@ pref("media.preload.auto", 2); // preload metadata if preload=auto
|
|||||||
// of at least 4.
|
// of at least 4.
|
||||||
pref("media.video-queue.default-size", 3);
|
pref("media.video-queue.default-size", 3);
|
||||||
|
|
||||||
|
// Enable the MediaCodec PlatformDecoderModule by default.
|
||||||
|
pref("media.fragmented-mp4.exposed", true);
|
||||||
|
pref("media.fragmented-mp4.enabled", true);
|
||||||
|
pref("media.fragmented-mp4.android-media-codec.enabled", true);
|
||||||
|
pref("media.fragmented-mp4.android-media-codec.preferred", true);
|
||||||
|
|
||||||
// optimize images memory usage
|
// optimize images memory usage
|
||||||
pref("image.mem.decodeondraw", true);
|
pref("image.mem.decodeondraw", true);
|
||||||
pref("image.mem.min_discard_timeout_ms", 10000);
|
pref("image.mem.min_discard_timeout_ms", 10000);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIScriptError.h"
|
#include "nsIScriptError.h"
|
||||||
#include "nsIHttpChannel.h"
|
#include "nsIHttpChannel.h"
|
||||||
|
#include "GeneratedSDKWrappers.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::widget::android;
|
using namespace mozilla::widget::android;
|
||||||
@ -220,6 +221,11 @@ AndroidBridge::Init(JNIEnv *jEnv)
|
|||||||
|
|
||||||
InitAndroidJavaWrappers(jEnv);
|
InitAndroidJavaWrappers(jEnv);
|
||||||
|
|
||||||
|
if (mAPIVersion >= 16 /* Jelly Bean */) {
|
||||||
|
// We only use this for MediaCodec right now
|
||||||
|
InitSDKStubs(jEnv);
|
||||||
|
}
|
||||||
|
|
||||||
// jEnv should NOT be cached here by anything -- the jEnv here
|
// jEnv should NOT be cached here by anything -- the jEnv here
|
||||||
// is not valid for the real gecko main thread, which is set
|
// is not valid for the real gecko main thread, which is set
|
||||||
// at SetMainThread time.
|
// at SetMainThread time.
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "mozilla/BasicEvents.h"
|
#include "mozilla/BasicEvents.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/TouchEvents.h"
|
#include "mozilla/TouchEvents.h"
|
||||||
|
#include "GeneratedSDKWrappers.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
1859
widget/android/GeneratedSDKWrappers.cpp
Normal file
1859
widget/android/GeneratedSDKWrappers.cpp
Normal file
File diff suppressed because it is too large
Load Diff
332
widget/android/GeneratedSDKWrappers.h
Normal file
332
widget/android/GeneratedSDKWrappers.h
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
// GENERATED CODE
|
||||||
|
|
||||||
|
// NOTE: This code has been doctored. The JarClassProcessor is still a work in progress,
|
||||||
|
// and so additions and deletions have been made to make this file valid.
|
||||||
|
|
||||||
|
// Generated by the Java program at /build/jarClassProcessors at compile time from
|
||||||
|
// a given set of jars and a set of requested methods. To update, change the annotations
|
||||||
|
// on the corresponding Java methods and rerun the build. Manually updating this file
|
||||||
|
// will cause your build to fail.
|
||||||
|
|
||||||
|
#ifndef GeneratedSDKWrappers_h__
|
||||||
|
#define GeneratedSDKWrappers_h__
|
||||||
|
|
||||||
|
#include "nsXPCOMStrings.h"
|
||||||
|
#include "AndroidJavaWrappers.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace widget {
|
||||||
|
namespace android {
|
||||||
|
void InitSDKStubs(JNIEnv *jEnv);
|
||||||
|
|
||||||
|
class MediaCodec : public AutoGlobalWrappedJavaObject {
|
||||||
|
public:
|
||||||
|
static void InitStubs(JNIEnv *jEnv);
|
||||||
|
static MediaCodec* Wrap(jobject obj);
|
||||||
|
MediaCodec(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
|
||||||
|
void Configure(jobject a0, jobject a1, jobject a2, int32_t a3);
|
||||||
|
static jobject CreateByCodecName(const nsAString& a0);
|
||||||
|
static jobject CreateDecoderByType(const nsAString& a0);
|
||||||
|
static jobject CreateEncoderByType(const nsAString& a0);
|
||||||
|
int32_t DequeueInputBuffer(int64_t a0);
|
||||||
|
int32_t DequeueOutputBuffer(jobject a0, int64_t a1);
|
||||||
|
void Finalize();
|
||||||
|
void Flush();
|
||||||
|
jobjectArray GetInputBuffers();
|
||||||
|
jobjectArray GetOutputBuffers();
|
||||||
|
jobject GetOutputFormat();
|
||||||
|
void QueueInputBuffer(int32_t a0, int32_t a1, int32_t a2, int64_t a3, int32_t a4);
|
||||||
|
void QueueSecureInputBuffer(int32_t a0, int32_t a1, jobject a2, int64_t a3, int32_t a4);
|
||||||
|
void Release();
|
||||||
|
void ReleaseOutputBuffer(int32_t a0, bool a1);
|
||||||
|
void SetVideoScalingMode(int32_t a0);
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
|
static int32_t getBUFFER_FLAG_CODEC_CONFIG();
|
||||||
|
static int32_t getBUFFER_FLAG_END_OF_STREAM();
|
||||||
|
static int32_t getBUFFER_FLAG_SYNC_FRAME();
|
||||||
|
static int32_t getCONFIGURE_FLAG_ENCODE();
|
||||||
|
static int32_t getCRYPTO_MODE_AES_CTR();
|
||||||
|
static int32_t getCRYPTO_MODE_UNENCRYPTED();
|
||||||
|
static int32_t getINFO_OUTPUT_BUFFERS_CHANGED();
|
||||||
|
static int32_t getINFO_OUTPUT_FORMAT_CHANGED();
|
||||||
|
static int32_t getINFO_TRY_AGAIN_LATER();
|
||||||
|
static int32_t getVIDEO_SCALING_MODE_SCALE_TO_FIT();
|
||||||
|
static int32_t getVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING();
|
||||||
|
MediaCodec() : AutoGlobalWrappedJavaObject() {};
|
||||||
|
protected:
|
||||||
|
static jclass mMediaCodecClass;
|
||||||
|
static jmethodID jConfigure;
|
||||||
|
static jmethodID jCreateByCodecName;
|
||||||
|
static jmethodID jCreateDecoderByType;
|
||||||
|
static jmethodID jCreateEncoderByType;
|
||||||
|
static jmethodID jDequeueInputBuffer;
|
||||||
|
static jmethodID jDequeueOutputBuffer;
|
||||||
|
static jmethodID jFinalize;
|
||||||
|
static jmethodID jFlush;
|
||||||
|
static jmethodID jGetInputBuffers;
|
||||||
|
static jmethodID jGetOutputBuffers;
|
||||||
|
static jmethodID jGetOutputFormat;
|
||||||
|
static jmethodID jQueueInputBuffer;
|
||||||
|
static jmethodID jQueueSecureInputBuffer;
|
||||||
|
static jmethodID jRelease;
|
||||||
|
static jmethodID jReleaseOutputBuffer;
|
||||||
|
static jmethodID jSetVideoScalingMode;
|
||||||
|
static jmethodID jStart;
|
||||||
|
static jmethodID jStop;
|
||||||
|
static jfieldID jBUFFER_FLAG_CODEC_CONFIG;
|
||||||
|
static jfieldID jBUFFER_FLAG_END_OF_STREAM;
|
||||||
|
static jfieldID jBUFFER_FLAG_SYNC_FRAME;
|
||||||
|
static jfieldID jCONFIGURE_FLAG_ENCODE;
|
||||||
|
static jfieldID jCRYPTO_MODE_AES_CTR;
|
||||||
|
static jfieldID jCRYPTO_MODE_UNENCRYPTED;
|
||||||
|
static jfieldID jINFO_OUTPUT_BUFFERS_CHANGED;
|
||||||
|
static jfieldID jINFO_OUTPUT_FORMAT_CHANGED;
|
||||||
|
static jfieldID jINFO_TRY_AGAIN_LATER;
|
||||||
|
static jfieldID jVIDEO_SCALING_MODE_SCALE_TO_FIT;
|
||||||
|
static jfieldID jVIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MediaFormat : public AutoGlobalWrappedJavaObject {
|
||||||
|
public:
|
||||||
|
static void InitStubs(JNIEnv *jEnv);
|
||||||
|
static MediaFormat* Wrap(jobject obj);
|
||||||
|
MediaFormat(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
|
||||||
|
MediaFormat();
|
||||||
|
bool ContainsKey(const nsAString& a0);
|
||||||
|
static jobject CreateAudioFormat(const nsAString& a0, int32_t a1, int32_t a2);
|
||||||
|
static jobject CreateVideoFormat(const nsAString& a0, int32_t a1, int32_t a2);
|
||||||
|
jobject GetByteBuffer(const nsAString& a0);
|
||||||
|
jfloat GetFloat(const nsAString& a0);
|
||||||
|
int32_t GetInteger(const nsAString& a0);
|
||||||
|
int64_t GetLong(const nsAString& a0);
|
||||||
|
jstring GetString(const nsAString& a0);
|
||||||
|
void SetByteBuffer(const nsAString& a0, jobject a1);
|
||||||
|
void SetFloat(const nsAString& a0, jfloat a1);
|
||||||
|
void SetInteger(const nsAString& a0, int32_t a1);
|
||||||
|
void SetLong(const nsAString& a0, int64_t a1);
|
||||||
|
void SetString(const nsAString& a0, const nsAString& a1);
|
||||||
|
jstring ToString();
|
||||||
|
static jstring getKEY_AAC_PROFILE();
|
||||||
|
static jstring getKEY_BIT_RATE();
|
||||||
|
static jstring getKEY_CHANNEL_COUNT();
|
||||||
|
static jstring getKEY_CHANNEL_MASK();
|
||||||
|
static jstring getKEY_COLOR_FORMAT();
|
||||||
|
static jstring getKEY_DURATION();
|
||||||
|
static jstring getKEY_FLAC_COMPRESSION_LEVEL();
|
||||||
|
static jstring getKEY_FRAME_RATE();
|
||||||
|
static jstring getKEY_HEIGHT();
|
||||||
|
static jstring getKEY_IS_ADTS();
|
||||||
|
static jstring getKEY_I_FRAME_INTERVAL();
|
||||||
|
static jstring getKEY_MAX_INPUT_SIZE();
|
||||||
|
static jstring getKEY_MIME();
|
||||||
|
static jstring getKEY_SAMPLE_RATE();
|
||||||
|
static jstring getKEY_WIDTH();
|
||||||
|
protected:
|
||||||
|
static jclass mMediaFormatClass;
|
||||||
|
static jmethodID jMediaFormat;
|
||||||
|
static jmethodID jContainsKey;
|
||||||
|
static jmethodID jCreateAudioFormat;
|
||||||
|
static jmethodID jCreateVideoFormat;
|
||||||
|
static jmethodID jGetByteBuffer;
|
||||||
|
static jmethodID jGetFloat;
|
||||||
|
static jmethodID jGetInteger;
|
||||||
|
static jmethodID jGetLong;
|
||||||
|
static jmethodID jGetString;
|
||||||
|
static jmethodID jSetByteBuffer;
|
||||||
|
static jmethodID jSetFloat;
|
||||||
|
static jmethodID jSetInteger;
|
||||||
|
static jmethodID jSetLong;
|
||||||
|
static jmethodID jSetString;
|
||||||
|
static jmethodID jToString;
|
||||||
|
static jfieldID jKEY_AAC_PROFILE;
|
||||||
|
static jfieldID jKEY_BIT_RATE;
|
||||||
|
static jfieldID jKEY_CHANNEL_COUNT;
|
||||||
|
static jfieldID jKEY_CHANNEL_MASK;
|
||||||
|
static jfieldID jKEY_COLOR_FORMAT;
|
||||||
|
static jfieldID jKEY_DURATION;
|
||||||
|
static jfieldID jKEY_FLAC_COMPRESSION_LEVEL;
|
||||||
|
static jfieldID jKEY_FRAME_RATE;
|
||||||
|
static jfieldID jKEY_HEIGHT;
|
||||||
|
static jfieldID jKEY_IS_ADTS;
|
||||||
|
static jfieldID jKEY_I_FRAME_INTERVAL;
|
||||||
|
static jfieldID jKEY_MAX_INPUT_SIZE;
|
||||||
|
static jfieldID jKEY_MIME;
|
||||||
|
static jfieldID jKEY_SAMPLE_RATE;
|
||||||
|
static jfieldID jKEY_WIDTH;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ByteBuffer : public AutoGlobalWrappedJavaObject {
|
||||||
|
public:
|
||||||
|
static void InitStubs(JNIEnv *jEnv);
|
||||||
|
static ByteBuffer* Wrap(jobject obj);
|
||||||
|
ByteBuffer(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
|
||||||
|
int8_t _get(int32_t a0);
|
||||||
|
void _put(int32_t a0, int8_t a1);
|
||||||
|
static jobject Allocate(int32_t a0);
|
||||||
|
static jobject AllocateDirect(int32_t a0);
|
||||||
|
jobject Array();
|
||||||
|
jbyteArray Array1();
|
||||||
|
int32_t ArrayOffset();
|
||||||
|
jstring AsCharBuffer();
|
||||||
|
jobject AsDoubleBuffer();
|
||||||
|
jobject AsFloatBuffer();
|
||||||
|
jobject AsIntBuffer();
|
||||||
|
jobject AsLongBuffer();
|
||||||
|
jobject AsReadOnlyBuffer();
|
||||||
|
jobject AsShortBuffer();
|
||||||
|
jobject Compact();
|
||||||
|
int32_t CompareTo(jobject a0);
|
||||||
|
int32_t CompareTo1(jobject a0);
|
||||||
|
jobject Duplicate();
|
||||||
|
bool Equals(jobject a0);
|
||||||
|
int8_t Get();
|
||||||
|
int8_t Get1(int32_t a0);
|
||||||
|
jobject Get1(jbyteArray a0);
|
||||||
|
jobject Get1(jbyteArray a0, int32_t a1, int32_t a2);
|
||||||
|
uint16_t GetChar();
|
||||||
|
uint16_t GetChar1(int32_t a0);
|
||||||
|
jdouble GetDouble();
|
||||||
|
jdouble GetDouble1(int32_t a0);
|
||||||
|
jfloat GetFloat();
|
||||||
|
jfloat GetFloat1(int32_t a0);
|
||||||
|
int32_t GetInt();
|
||||||
|
int32_t GetInt1(int32_t a0);
|
||||||
|
int64_t GetLong();
|
||||||
|
int64_t GetLong1(int32_t a0);
|
||||||
|
int16_t GetShort();
|
||||||
|
int16_t GetShort1(int32_t a0);
|
||||||
|
bool HasArray();
|
||||||
|
int32_t HashCode();
|
||||||
|
bool IsDirect();
|
||||||
|
jobject Order();
|
||||||
|
jobject Order1(jobject a0);
|
||||||
|
jobject Put(int8_t a0);
|
||||||
|
jobject Put1(int32_t a0, int8_t a1);
|
||||||
|
jobject Put1(jobject a0);
|
||||||
|
jobject Put1(jbyteArray a0);
|
||||||
|
jobject Put1(jbyteArray a0, int32_t a1, int32_t a2);
|
||||||
|
jobject PutChar(uint16_t a0);
|
||||||
|
jobject PutChar1(int32_t a0, uint16_t a1);
|
||||||
|
jobject PutDouble(jdouble a0);
|
||||||
|
jobject PutDouble1(int32_t a0, jdouble a1);
|
||||||
|
jobject PutFloat(jfloat a0);
|
||||||
|
jobject PutFloat1(int32_t a0, jfloat a1);
|
||||||
|
jobject PutInt(int32_t a0);
|
||||||
|
jobject PutInt1(int32_t a0, int32_t a1);
|
||||||
|
jobject PutLong(int32_t a0, int64_t a1);
|
||||||
|
jobject PutLong1(int64_t a0);
|
||||||
|
jobject PutShort(int32_t a0, int16_t a1);
|
||||||
|
jobject PutShort1(int16_t a0);
|
||||||
|
jobject Slice();
|
||||||
|
jstring ToString();
|
||||||
|
static jobject Wrap1(jbyteArray a0);
|
||||||
|
static jobject Wrap2(jbyteArray a0, int32_t a1, int32_t a2);
|
||||||
|
bool getBigEndian();
|
||||||
|
void setBigEndian(bool a0);
|
||||||
|
jbyteArray getHb();
|
||||||
|
bool getIsReadOnly();
|
||||||
|
void setIsReadOnly(bool a0);
|
||||||
|
bool getNativeByteOrder();
|
||||||
|
void setNativeByteOrder(bool a0);
|
||||||
|
int32_t getOffset();
|
||||||
|
ByteBuffer() : AutoGlobalWrappedJavaObject() {};
|
||||||
|
protected:
|
||||||
|
static jclass mByteBufferClass;
|
||||||
|
static jmethodID j_get;
|
||||||
|
static jmethodID j_put;
|
||||||
|
static jmethodID jAllocate;
|
||||||
|
static jmethodID jAllocateDirect;
|
||||||
|
static jmethodID jArray;
|
||||||
|
static jmethodID jArray1;
|
||||||
|
static jmethodID jArrayOffset;
|
||||||
|
static jmethodID jAsCharBuffer;
|
||||||
|
static jmethodID jAsDoubleBuffer;
|
||||||
|
static jmethodID jAsFloatBuffer;
|
||||||
|
static jmethodID jAsIntBuffer;
|
||||||
|
static jmethodID jAsLongBuffer;
|
||||||
|
static jmethodID jAsReadOnlyBuffer;
|
||||||
|
static jmethodID jAsShortBuffer;
|
||||||
|
static jmethodID jCompact;
|
||||||
|
static jmethodID jCompareTo;
|
||||||
|
static jmethodID jCompareTo1;
|
||||||
|
static jmethodID jDuplicate;
|
||||||
|
static jmethodID jEquals;
|
||||||
|
static jmethodID jGet;
|
||||||
|
static jmethodID jGet1;
|
||||||
|
static jmethodID jGet10;
|
||||||
|
static jmethodID jGet11;
|
||||||
|
static jmethodID jGetChar;
|
||||||
|
static jmethodID jGetChar1;
|
||||||
|
static jmethodID jGetDouble;
|
||||||
|
static jmethodID jGetDouble1;
|
||||||
|
static jmethodID jGetFloat;
|
||||||
|
static jmethodID jGetFloat1;
|
||||||
|
static jmethodID jGetInt;
|
||||||
|
static jmethodID jGetInt1;
|
||||||
|
static jmethodID jGetLong;
|
||||||
|
static jmethodID jGetLong1;
|
||||||
|
static jmethodID jGetShort;
|
||||||
|
static jmethodID jGetShort1;
|
||||||
|
static jmethodID jHasArray;
|
||||||
|
static jmethodID jHashCode;
|
||||||
|
static jmethodID jIsDirect;
|
||||||
|
static jmethodID jOrder;
|
||||||
|
static jmethodID jOrder1;
|
||||||
|
static jmethodID jPut;
|
||||||
|
static jmethodID jPut1;
|
||||||
|
static jmethodID jPut12;
|
||||||
|
static jmethodID jPut13;
|
||||||
|
static jmethodID jPut14;
|
||||||
|
static jmethodID jPutChar;
|
||||||
|
static jmethodID jPutChar1;
|
||||||
|
static jmethodID jPutDouble;
|
||||||
|
static jmethodID jPutDouble1;
|
||||||
|
static jmethodID jPutFloat;
|
||||||
|
static jmethodID jPutFloat1;
|
||||||
|
static jmethodID jPutInt;
|
||||||
|
static jmethodID jPutInt1;
|
||||||
|
static jmethodID jPutLong;
|
||||||
|
static jmethodID jPutLong1;
|
||||||
|
static jmethodID jPutShort;
|
||||||
|
static jmethodID jPutShort1;
|
||||||
|
static jmethodID jSlice;
|
||||||
|
static jmethodID jToString;
|
||||||
|
static jmethodID jWrap;
|
||||||
|
static jmethodID jWrap1;
|
||||||
|
static jfieldID jBigEndian;
|
||||||
|
static jfieldID jHb;
|
||||||
|
static jfieldID jIsReadOnly;
|
||||||
|
static jfieldID jNativeByteOrder;
|
||||||
|
static jfieldID jOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BufferInfo : public AutoGlobalWrappedJavaObject {
|
||||||
|
public:
|
||||||
|
static void InitStubs(JNIEnv *jEnv);
|
||||||
|
static BufferInfo* Wrap(jobject obj);
|
||||||
|
BufferInfo(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
|
||||||
|
BufferInfo();
|
||||||
|
void Set(int32_t a0, int32_t a1, int64_t a2, int32_t a3);
|
||||||
|
int32_t getFlags();
|
||||||
|
void setFlags(int32_t a0);
|
||||||
|
int32_t getOffset();
|
||||||
|
void setOffset(int32_t a0);
|
||||||
|
int64_t getPresentationTimeUs();
|
||||||
|
void setPresentationTimeUs(int64_t a0);
|
||||||
|
int32_t getSize();
|
||||||
|
void setSize(int32_t a0);
|
||||||
|
protected:
|
||||||
|
static jclass mBufferInfoClass;
|
||||||
|
static jmethodID jBufferInfo;
|
||||||
|
static jmethodID jSet;
|
||||||
|
static jfieldID jFlags;
|
||||||
|
static jfieldID jOffset;
|
||||||
|
static jfieldID jPresentationTimeUs;
|
||||||
|
static jfieldID jSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* android */
|
||||||
|
} /* widget */
|
||||||
|
} /* mozilla */
|
||||||
|
#endif
|
@ -15,6 +15,7 @@ EXPORTS += [
|
|||||||
'AndroidJavaWrappers.h',
|
'AndroidJavaWrappers.h',
|
||||||
'AndroidJNIWrapper.h',
|
'AndroidJNIWrapper.h',
|
||||||
'GeneratedJNIWrappers.h',
|
'GeneratedJNIWrappers.h',
|
||||||
|
'GeneratedSDKWrappers.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
@ -26,6 +27,7 @@ SOURCES += [
|
|||||||
'AndroidJNIWrapper.cpp',
|
'AndroidJNIWrapper.cpp',
|
||||||
'APZCCallbackHandler.cpp',
|
'APZCCallbackHandler.cpp',
|
||||||
'GeneratedJNIWrappers.cpp',
|
'GeneratedJNIWrappers.cpp',
|
||||||
|
'GeneratedSDKWrappers.cpp',
|
||||||
'GfxInfo.cpp',
|
'GfxInfo.cpp',
|
||||||
'NativeJSContainer.cpp',
|
'NativeJSContainer.cpp',
|
||||||
'nsAndroidProtocolHandler.cpp',
|
'nsAndroidProtocolHandler.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user