Bug 1106958 - Use android.media.MediaCodec for decoding in WebRTC stack. r=snorp, r=gcp, r=ted

This commit is contained in:
Qiang Lu 2014-12-10 11:06:06 +08:00
parent fbc0db20fa
commit 369ac82eca
8 changed files with 1266 additions and 1 deletions

View File

@ -44,6 +44,7 @@ gyp_vars = {
'moz_widget_toolkit_gonk': 0,
'moz_webrtc_omx': 0,
'moz_webrtc_mediacodec': 0,
# (for vp8) chromium sets to 0 also
'use_temporal_layers': 0,
@ -80,6 +81,7 @@ elif os == 'Android':
else:
gyp_vars.update(
gtest_target_type='executable',
moz_webrtc_mediacodec=1,
android_toolchain=CONFIG['ANDROID_TOOLCHAIN'],
)

View File

@ -58,7 +58,9 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']:
'signaling/src/jsep/JsepSessionImpl.cpp',
'signaling/src/media-conduit/AudioConduit.cpp',
'signaling/src/media-conduit/CodecStatistics.cpp',
'signaling/src/media-conduit/MediaCodecVideoCodec.cpp',
'signaling/src/media-conduit/VideoConduit.cpp',
'signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp',
'signaling/src/mediapipeline/MediaPipeline.cpp',
'signaling/src/mediapipeline/MediaPipelineFilter.cpp',
'signaling/src/mediapipeline/SrtpFlow.cpp',
@ -94,6 +96,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
GYP_DIRS['signalingtest'].variables = gyp_vars.copy()
GYP_DIRS['signalingtest'].variables.update(
build_for_test=1,
moz_webrtc_mediacodec=0,
build_for_standalone=0
)
GYP_DIRS['signalingtest'].non_unified_sources += signaling_non_unified_sources

View File

@ -216,6 +216,20 @@
'MOZ_WEBRTC_OMX'
],
}],
['moz_webrtc_mediacodec==1', {
'include_dirs': [
'../../../widget/android',
],
'sources': [
'./src/media-conduit/MediaCodecVideoCodec.h',
'./src/media-conduit/WebrtcMediaCodecVP8VideoCodec.h',
'./src/media-conduit/MediaCodecVideoCodec.cpp',
'./src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp',
],
'defines' : [
'MOZ_WEBRTC_MEDIACODEC',
],
}],
['(build_for_test==0) and (build_for_standalone==0)', {
'defines' : [
'MOZILLA_INTERNAL_API',

View File

@ -0,0 +1,31 @@
/* 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 "CSFLog.h"
#include "nspr.h"
#include "WebrtcMediaCodecVP8VideoCodec.h"
#include "MediaCodecVideoCodec.h"
namespace mozilla {
static const char* logTag ="MediaCodecVideoCodec";
VideoEncoder* MediaCodecVideoCodec::CreateEncoder(CodecType aCodecType) {
CSFLogDebug(logTag, "%s ", __FUNCTION__);
if (aCodecType == CODEC_VP8) {
return new WebrtcMediaCodecVP8VideoEncoder();
}
return nullptr;
}
VideoDecoder* MediaCodecVideoCodec::CreateDecoder(CodecType aCodecType) {
CSFLogDebug(logTag, "%s ", __FUNCTION__);
if (aCodecType == CODEC_VP8) {
return new WebrtcMediaCodecVP8VideoDecoder();
}
return nullptr;
}
}

View File

@ -0,0 +1,31 @@
/* 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 MediaCodecVideoCodec_h__
#define MediaCodecVideoCodec_h__
#include "MediaConduitInterface.h"
namespace mozilla {
class MediaCodecVideoCodec {
public:
enum CodecType {
CODEC_VP8,
};
/**
* Create encoder object for codec type |aCodecType|. Return |nullptr| when
* failed.
*/
static VideoEncoder* CreateEncoder(CodecType aCodecType);
/**
* Create decoder object for codec type |aCodecType|. Return |nullptr| when
* failed.
*/
static VideoDecoder* CreateDecoder(CodecType aCodecType);
};
}
#endif // MediaCodecVideoCodec_h__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
/* 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 WebrtcMediaCodecVP8VideoCodec_h__
#define WebrtcMediaCodecVP8VideoCodec_h__
#include "mozilla/Mutex.h"
#include "nsThreadUtils.h"
#include "nsAutoPtr.h"
#include "MediaConduitInterface.h"
#include "AudioConduit.h"
#include "VideoConduit.h"
namespace mozilla {
struct EncodedFrame {
uint32_t width_;
uint32_t height_;
uint32_t timeStamp_;
uint64_t decode_timestamp_;
};
class WebrtcAndroidMediaCodec;
class WebrtcMediaCodecVP8VideoEncoder : public WebrtcVideoEncoder {
public:
WebrtcMediaCodecVP8VideoEncoder();
virtual ~WebrtcMediaCodecVP8VideoEncoder() override;
// Implement VideoEncoder interface.
virtual const uint64_t PluginID() override { return 0; }
virtual int32_t InitEncode(const webrtc::VideoCodec* codecSettings,
int32_t numberOfCores,
uint32_t maxPayloadSize) override;
virtual int32_t Encode(const webrtc::I420VideoFrame& inputImage,
const webrtc::CodecSpecificInfo* codecSpecificInfo,
const std::vector<webrtc::VideoFrameType>* frame_types) override;
virtual int32_t RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback* callback) override;
virtual int32_t Release() override;
virtual int32_t SetChannelParameters(uint32_t packetLoss, int rtt) override;
virtual int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override;
private:
int32_t VerifyAndAllocate(const uint32_t minimumSize);
bool ResetInputBuffers();
bool ResetOutputBuffers();
size_t mMaxPayloadSize;
uint32_t mTimestamp;
webrtc::EncodedImage mEncodedImage;
webrtc::EncodedImageCallback* mCallback;
uint32_t mFrameWidth;
uint32_t mFrameHeight;
WebrtcAndroidMediaCodec* mMediaCodecEncoder;
jobjectArray mInputBuffers;
jobjectArray mOutputBuffers;
};
class WebrtcMediaCodecVP8VideoDecoder : public WebrtcVideoDecoder {
public:
WebrtcMediaCodecVP8VideoDecoder();
virtual ~WebrtcMediaCodecVP8VideoDecoder() override;
// Implement VideoDecoder interface.
virtual const uint64_t PluginID() override { return 0; }
virtual int32_t InitDecode(const webrtc::VideoCodec* codecSettings,
int32_t numberOfCores) override;
virtual int32_t Decode(const webrtc::EncodedImage& inputImage,
bool missingFrames,
const webrtc::RTPFragmentationHeader* fragmentation,
const webrtc::CodecSpecificInfo*
codecSpecificInfo = NULL,
int64_t renderTimeMs = -1) override;
virtual int32_t RegisterDecodeCompleteCallback(webrtc::DecodedImageCallback* callback) override;
virtual int32_t Release() override;
virtual int32_t Reset() override;
private:
void DecodeFrame(EncodedFrame* frame);
void RunCallback();
bool ResetInputBuffers();
bool ResetOutputBuffers();
webrtc::DecodedImageCallback* mCallback;
uint32_t mFrameWidth;
uint32_t mFrameHeight;
WebrtcAndroidMediaCodec* mMediaCodecDecoder;
jobjectArray mInputBuffers;
jobjectArray mOutputBuffers;
};
}
#endif // WebrtcMediaCodecVP8VideoCodec_h__

View File

@ -3,6 +3,8 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "logging.h"
#include "nsIGfxInfo.h"
#include "nsServiceManagerUtils.h"
#include "PeerConnectionImpl.h"
#include "PeerConnectionMedia.h"
@ -30,6 +32,14 @@
#include "OMXCodecWrapper.h"
#endif
#ifdef MOZ_WEBRTC_MEDIACODEC
#include "MediaCodecVideoCodec.h"
#endif
#ifdef MOZILLA_INTERNAL_API
#include "mozilla/Preferences.h"
#endif
#include <stdlib.h>
namespace mozilla {
@ -846,7 +856,63 @@ MediaPipelineFactory::EnsureExternalCodec(VideoSessionConduit& aConduit,
VideoCodecConfig* aConfig,
bool aIsSend)
{
if (aConfig->mName == "VP8" || aConfig->mName == "VP9") {
if (aConfig->mName == "VP8") {
#ifdef MOZ_WEBRTC_MEDIACODEC
if (aIsSend) {
#ifdef MOZILLA_INTERNAL_API
bool enabled = mozilla::Preferences::GetBool("media.navigator.hardware.vp8_encode.acceleration_enabled", false);
#else
bool enabled = false;
#endif
if (enabled) {
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (gfxInfo) {
int32_t status;
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION, &status))) {
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
NS_WARNING("VP8 encoder hardware is not whitelisted: disabling.\n");
} else {
VideoEncoder* encoder = nullptr;
encoder = MediaCodecVideoCodec::CreateEncoder(MediaCodecVideoCodec::CodecType::CODEC_VP8);
if (encoder) {
return aConduit.SetExternalSendCodec(aConfig, encoder);
} else {
return kMediaConduitNoError;
}
}
}
}
}
} else {
#ifdef MOZILLA_INTERNAL_API
bool enabled = mozilla::Preferences::GetBool("media.navigator.hardware.vp8_decode.acceleration_enabled", false);
#else
bool enabled = false;
#endif
if (enabled) {
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (gfxInfo) {
int32_t status;
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION, &status))) {
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
NS_WARNING("VP8 decoder hardware is not whitelisted: disabling.\n");
} else {
VideoDecoder* decoder;
decoder = MediaCodecVideoCodec::CreateDecoder(MediaCodecVideoCodec::CodecType::CODEC_VP8);
if (decoder) {
return aConduit.SetExternalRecvCodec(aConfig, decoder);
} else {
return kMediaConduitNoError;
}
}
}
}
}
}
#endif
return kMediaConduitNoError;
} else if (aConfig->mName == "VP9") {
return kMediaConduitNoError;
} else if (aConfig->mName == "H264") {
if (aConduit.CodecPluginID() != 0) {