--- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
@@ -765,24 +765,18 @@ WebrtcGmpVideoDecoder::GmpInitDone(GMPVi
}
// now release any frames that got queued waiting for InitDone
if (!mQueuedFrames.IsEmpty()) {
// So we're safe to call Decode_g(), which asserts it's empty
nsTArray<UniquePtr<GMPDecodeData>> temp;
temp.SwapElements(mQueuedFrames);
for (auto& queued : temp) {
- int rv = Decode_g(queued->mImage,
- queued->mMissingFrames,
- nullptr,
- nullptr,
- queued->mRenderTimeMs);
- if (rv) {
- return rv;
- }
+ Decode_g(RefPtr<WebrtcGmpVideoDecoder>(this),
+ nsAutoPtr<GMPDecodeData>(queued.release()));
}
}
return WEBRTC_VIDEO_CODEC_OK;
}
void
WebrtcGmpVideoDecoder::Close_g()
@@ -800,114 +794,116 @@ WebrtcGmpVideoDecoder::Close_g()
int32_t
WebrtcGmpVideoDecoder::Decode(const webrtc::EncodedImage& aInputImage,
bool aMissingFrames,
const webrtc::RTPFragmentationHeader* aFragmentation,
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
int64_t aRenderTimeMs)
{
- int32_t ret;
MOZ_ASSERT(mGMPThread);
MOZ_ASSERT(!NS_IsMainThread());
- // Would be really nice to avoid this sync dispatch, but it would require a
- // copy of the frame, since it doesn't appear to actually have a refcount.
- // Passing 'this' is safe since this is synchronous.
- mozilla::SyncRunnable::DispatchToThread(mGMPThread,
- WrapRunnableRet(&ret, this,
- &WebrtcGmpVideoDecoder::Decode_g,
- aInputImage,
- aMissingFrames,
- aFragmentation,
- aCodecSpecificInfo,
- aRenderTimeMs));
-
- return ret;
-}
-
-int32_t
-WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage,
- bool aMissingFrames,
- const webrtc::RTPFragmentationHeader* aFragmentation,
- const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
- int64_t aRenderTimeMs)
-{
- if (!mGMP) {
- if (mInitting) {
- // InitDone hasn't been called yet (race)
- GMPDecodeData *data = new GMPDecodeData(aInputImage,
- aMissingFrames,
- aRenderTimeMs);
- mQueuedFrames.AppendElement(data);
- return WEBRTC_VIDEO_CODEC_OK;
- }
- // destroyed via Terminate(), failed to init, or just not initted yet
- LOGD(("GMP Decode: not initted yet"));
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- MOZ_ASSERT(mQueuedFrames.IsEmpty());
- MOZ_ASSERT(mHost);
-
if (!aInputImage._length) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
+ nsAutoPtr<GMPDecodeData> decodeData(new GMPDecodeData(aInputImage,
+ aMissingFrames,
+ aRenderTimeMs));
+
+ mGMPThread->Dispatch(WrapRunnableNM(&WebrtcGmpVideoDecoder::Decode_g,
+ RefPtr<WebrtcGmpVideoDecoder>(this),
+ decodeData),
+ NS_DISPATCH_NORMAL);
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+/* static */
+// Using nsAutoPtr because WrapRunnable doesn't support move semantics
+void
+WebrtcGmpVideoDecoder::Decode_g(const RefPtr<WebrtcGmpVideoDecoder>& aThis,
+ nsAutoPtr<GMPDecodeData> aDecodeData)
+{
+ if (!aThis->mGMP) {
+ if (aThis->mInitting) {
+ // InitDone hasn't been called yet (race)
+ aThis->mQueuedFrames.AppendElement(aDecodeData.forget());
+ return;
+ }
+ // destroyed via Terminate(), failed to init, or just not initted yet
+ LOGD(("GMP Decode: not initted yet"));
+ return;
+ }
+
+ MOZ_ASSERT(aThis->mQueuedFrames.IsEmpty());
+ MOZ_ASSERT(aThis->mHost);
+
GMPVideoFrame* ftmp = nullptr;
- GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
+ GMPErr err = aThis->mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
if (err != GMPNoErr) {
- return WEBRTC_VIDEO_CODEC_ERROR;
+ LOG(LogLevel::Error, ("%s: CreateFrame failed (%u)!",
+ __PRETTY_FUNCTION__, static_cast<unsigned>(err)));
+ return;
}
GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
- err = frame->CreateEmptyFrame(aInputImage._length);
+ err = frame->CreateEmptyFrame(aDecodeData->mImage._length);
if (err != GMPNoErr) {
- return WEBRTC_VIDEO_CODEC_ERROR;
+ LOG(LogLevel::Error, ("%s: CreateEmptyFrame failed (%u)!",
+ __PRETTY_FUNCTION__, static_cast<unsigned>(err)));
+ return;
}
// XXX At this point, we only will get mode1 data (a single length and a buffer)
// Session_info.cc/etc code needs to change to support mode 0.
*(reinterpret_cast<uint32_t*>(frame->Buffer())) = frame->Size();
// XXX It'd be wonderful not to have to memcpy the encoded data!
- memcpy(frame->Buffer()+4, aInputImage._buffer+4, frame->Size()-4);
+ memcpy(frame->Buffer()+4, aDecodeData->mImage._buffer+4, frame->Size()-4);
- frame->SetEncodedWidth(aInputImage._encodedWidth);
- frame->SetEncodedHeight(aInputImage._encodedHeight);
- frame->SetTimeStamp((aInputImage._timeStamp * 1000ll)/90); // rounds down
- frame->SetCompleteFrame(aInputImage._completeFrame);
+ frame->SetEncodedWidth(aDecodeData->mImage._encodedWidth);
+ frame->SetEncodedHeight(aDecodeData->mImage._encodedHeight);
+ frame->SetTimeStamp((aDecodeData->mImage._timeStamp * 1000ll)/90); // rounds down
+ frame->SetCompleteFrame(aDecodeData->mImage._completeFrame);
frame->SetBufferType(GMP_BufferLength32);
GMPVideoFrameType ft;
- int32_t ret = WebrtcFrameTypeToGmpFrameType(aInputImage._frameType, &ft);
+ int32_t ret = WebrtcFrameTypeToGmpFrameType(aDecodeData->mImage._frameType, &ft);
if (ret != WEBRTC_VIDEO_CODEC_OK) {
- return ret;
+ LOG(LogLevel::Error, ("%s: WebrtcFrameTypeToGmpFrameType failed (%u)!",
+ __PRETTY_FUNCTION__, static_cast<unsigned>(ret)));
+ return;
}
// Bug XXXXXX: Set codecSpecific info
GMPCodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.mCodecType = kGMPVideoCodecH264;
info.mCodecSpecific.mH264.mSimulcastIdx = 0;
nsTArray<uint8_t> codecSpecificInfo;
codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
- LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(), aInputImage._length,
- ft == kGMPKeyFrame ? ", KeyFrame" : ""));
- nsresult rv = mGMP->Decode(Move(frame),
- aMissingFrames,
- codecSpecificInfo,
- aRenderTimeMs);
+ LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(),
+ aDecodeData->mImage._length, ft == kGMPKeyFrame ? ", KeyFrame" : ""));
+
+ nsresult rv = aThis->mGMP->Decode(Move(frame),
+ aDecodeData->mMissingFrames,
+ codecSpecificInfo,
+ aDecodeData->mRenderTimeMs);
if (NS_FAILED(rv)) {
- return WEBRTC_VIDEO_CODEC_ERROR;
+ LOG(LogLevel::Error, ("%s: Decode failed (rv=%u)!",
+ __PRETTY_FUNCTION__, static_cast<unsigned>(rv)));
}
- if(mDecoderStatus != GMPNoErr){
- mDecoderStatus = GMPNoErr;
- return WEBRTC_VIDEO_CODEC_ERROR;
+
+ if(aThis->mDecoderStatus != GMPNoErr){
+ aThis->mDecoderStatus = GMPNoErr;
+ LOG(LogLevel::Error, ("%s: Decoder status is bad (%u)!",
+ __PRETTY_FUNCTION__, static_cast<unsigned>(aThis->mDecoderStatus)));
}
- return WEBRTC_VIDEO_CODEC_OK;
}
int32_t
WebrtcGmpVideoDecoder::RegisterDecodeCompleteCallback( webrtc::DecodedImageCallback* aCallback)
{
MutexAutoLock lock(mCallbackMutex);
mCallback = aCallback;
--- a/media/webrtc/webrtc.mozbuild
+++ b/media/webrtc/webrtc.mozbuild
@@ -1,25 +1,29 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG['MOZ_WEBRTC']:
DEFINES['HAVE_UINT64_T'] = True
+
if CONFIG['OS_TARGET'] != 'WINNT':
DEFINES['WEBRTC_POSIX'] = True
DEFINES['WEBRTC_BUILD_LIBEVENT'] = True
if CONFIG['OS_TARGET'] == 'Linux':
DEFINES['WEBRTC_LINUX'] = True
elif CONFIG['OS_TARGET'] == 'Darwin':
DEFINES['WEBRTC_MAC'] = True
elif CONFIG['OS_TARGET'] == 'WINNT':
DEFINES['WEBRTC_WIN'] = True
DEFINES['HAVE_WINSOCK2_H'] = True
elif CONFIG['OS_TARGET'] in ('DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD'):
DEFINES['WEBRTC_BSD'] = True
elif CONFIG['OS_TARGET'] == 'Android':
DEFINES['WEBRTC_ANDROID'] = True
+ if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
+ DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
+
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']