diff options
Diffstat (limited to 'dom/media')
58 files changed, 11 insertions, 7966 deletions
diff --git a/dom/media/AudioStream.cpp b/dom/media/AudioStream.cpp index 82ae3ee86..54cf7b965 100644 --- a/dom/media/AudioStream.cpp +++ b/dom/media/AudioStream.cpp @@ -333,11 +333,7 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate, params.rate = aRate; params.channels = mOutChannels; #if defined(__ANDROID__) -#if defined(MOZ_B2G) - params.stream_type = CubebUtils::ConvertChannelToCubebType(aAudioChannel); -#else params.stream_type = CUBEB_STREAM_TYPE_MUSIC; -#endif if (params.stream_type == CUBEB_STREAM_TYPE_MAX) { return NS_ERROR_INVALID_ARG; diff --git a/dom/media/CubebUtils.cpp b/dom/media/CubebUtils.cpp index d1b4bae99..fe94264ee 100644 --- a/dom/media/CubebUtils.cpp +++ b/dom/media/CubebUtils.cpp @@ -342,33 +342,6 @@ uint32_t MaxNumberOfChannels() return 0; } -#if defined(__ANDROID__) && defined(MOZ_B2G) -cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel) -{ - switch(aChannel) { - case dom::AudioChannel::Normal: - /* FALLTHROUGH */ - case dom::AudioChannel::Content: - return CUBEB_STREAM_TYPE_MUSIC; - case dom::AudioChannel::Notification: - return CUBEB_STREAM_TYPE_NOTIFICATION; - case dom::AudioChannel::Alarm: - return CUBEB_STREAM_TYPE_ALARM; - case dom::AudioChannel::Telephony: - return CUBEB_STREAM_TYPE_VOICE_CALL; - case dom::AudioChannel::Ringer: - return CUBEB_STREAM_TYPE_RING; - case dom::AudioChannel::System: - return CUBEB_STREAM_TYPE_SYSTEM; - case dom::AudioChannel::Publicnotification: - return CUBEB_STREAM_TYPE_SYSTEM_ENFORCED; - default: - NS_ERROR("The value of AudioChannel is invalid"); - return CUBEB_STREAM_TYPE_MAX; - } -} -#endif - void GetCurrentBackend(nsAString& aBackend) { cubeb* cubebContext = GetCubebContext(); diff --git a/dom/media/CubebUtils.h b/dom/media/CubebUtils.h index 171c244b7..fa5fc2294 100644 --- a/dom/media/CubebUtils.h +++ b/dom/media/CubebUtils.h @@ -40,9 +40,6 @@ void ReportCubebBackendUsed(); uint32_t GetCubebPlaybackLatencyInMilliseconds(); Maybe<uint32_t> GetCubebMSGLatencyInFrames(); bool CubebLatencyPrefSet(); -#if defined(__ANDROID__) && defined(MOZ_B2G) -cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel); -#endif void GetCurrentBackend(nsAString& aBackend); } // namespace CubebUtils diff --git a/dom/media/DOMMediaStream.cpp b/dom/media/DOMMediaStream.cpp index c1d451035..118d845a3 100755 --- a/dom/media/DOMMediaStream.cpp +++ b/dom/media/DOMMediaStream.cpp @@ -1505,20 +1505,6 @@ DOMAudioNodeMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWind DOMHwMediaStream::DOMHwMediaStream(nsPIDOMWindowInner* aWindow) : DOMLocalMediaStream(aWindow, nullptr) { -#ifdef MOZ_WIDGET_GONK - if (!mWindow) { - NS_ERROR("Expected window here."); - mPrincipalHandle = PRINCIPAL_HANDLE_NONE; - return; - } - nsIDocument* doc = mWindow->GetExtantDoc(); - if (!doc) { - NS_ERROR("Expected document here."); - mPrincipalHandle = PRINCIPAL_HANDLE_NONE; - return; - } - mPrincipalHandle = MakePrincipalHandle(doc->NodePrincipal()); -#endif } DOMHwMediaStream::~DOMHwMediaStream() @@ -1545,31 +1531,8 @@ DOMHwMediaStream::Init(MediaStream* stream, OverlayImage* aImage) { SourceMediaStream* srcStream = stream->AsSourceStream(); -#ifdef MOZ_WIDGET_GONK - if (aImage) { - mOverlayImage = aImage; - } else { - Data imageData; - imageData.mOverlayId = DEFAULT_IMAGE_ID; - imageData.mSize.width = DEFAULT_IMAGE_WIDTH; - imageData.mSize.height = DEFAULT_IMAGE_HEIGHT; - - mOverlayImage = new OverlayImage(); - mOverlayImage->SetData(imageData); - } -#endif - if (srcStream) { VideoSegment segment; -#ifdef MOZ_WIDGET_GONK - const StreamTime delta = STREAM_TIME_MAX; // Because MediaStreamGraph will run out frames in non-autoplay mode, - // we must give it bigger frame length to cover this situation. - - RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get()); - mozilla::gfx::IntSize size = image->GetSize(); - - segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle); -#endif srcStream->AddTrack(TRACK_VIDEO_PRIMARY, 0, new VideoSegment()); srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment); srcStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); @@ -1579,30 +1542,13 @@ DOMHwMediaStream::Init(MediaStream* stream, OverlayImage* aImage) int32_t DOMHwMediaStream::RequestOverlayId() { -#ifdef MOZ_WIDGET_GONK - return mOverlayImage->GetOverlayId(); -#else + /*** STUB ***/ return -1; -#endif } void DOMHwMediaStream::SetImageSize(uint32_t width, uint32_t height) { -#ifdef MOZ_WIDGET_GONK - if (mOverlayImage->GetSidebandStream().IsValid()) { - OverlayImage::SidebandStreamData imgData; - imgData.mStream = mOverlayImage->GetSidebandStream(); - imgData.mSize = IntSize(width, height); - mOverlayImage->SetData(imgData); - } else { - OverlayImage::Data imgData; - imgData.mOverlayId = mOverlayImage->GetOverlayId(); - imgData.mSize = IntSize(width, height); - mOverlayImage->SetData(imgData); - } -#endif - SourceMediaStream* srcStream = GetInputStream()->AsSourceStream(); StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY); @@ -1610,23 +1556,6 @@ DOMHwMediaStream::SetImageSize(uint32_t width, uint32_t height) return; } -#ifdef MOZ_WIDGET_GONK - // Clear the old segment. - // Changing the existing content of segment is a Very BAD thing, and this way will - // confuse consumers of MediaStreams. - // It is only acceptable for DOMHwMediaStream - // because DOMHwMediaStream doesn't have consumers of TV streams currently. - track->GetSegment()->Clear(); - - // Change the image size. - const StreamTime delta = STREAM_TIME_MAX; - RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get()); - mozilla::gfx::IntSize size = image->GetSize(); - VideoSegment segment; - - segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle); - srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment); -#endif } void @@ -1635,9 +1564,6 @@ DOMHwMediaStream::SetOverlayImage(OverlayImage* aImage) if (!aImage) { return; } -#ifdef MOZ_WIDGET_GONK - mOverlayImage = aImage; -#endif SourceMediaStream* srcStream = GetInputStream()->AsSourceStream(); StreamTracks::Track* track = srcStream->FindTrack(TRACK_VIDEO_PRIMARY); @@ -1646,34 +1572,10 @@ DOMHwMediaStream::SetOverlayImage(OverlayImage* aImage) return; } -#ifdef MOZ_WIDGET_GONK - // Clear the old segment. - // Changing the existing content of segment is a Very BAD thing, and this way will - // confuse consumers of MediaStreams. - // It is only acceptable for DOMHwMediaStream - // because DOMHwMediaStream doesn't have consumers of TV streams currently. - track->GetSegment()->Clear(); - - // Change the image size. - const StreamTime delta = STREAM_TIME_MAX; - RefPtr<Image> image = static_cast<Image*>(mOverlayImage.get()); - mozilla::gfx::IntSize size = image->GetSize(); - VideoSegment segment; - - segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle); - srcStream->AppendToTrack(TRACK_VIDEO_PRIMARY, &segment); -#endif } void DOMHwMediaStream::SetOverlayId(int32_t aOverlayId) { -#ifdef MOZ_WIDGET_GONK - OverlayImage::Data imgData; - - imgData.mOverlayId = aOverlayId; - imgData.mSize = mOverlayImage->GetSize(); - - mOverlayImage->SetData(imgData); -#endif + /*** STUB ***/ } diff --git a/dom/media/DOMMediaStream.h b/dom/media/DOMMediaStream.h index 12f3529a8..5618f8b00 100644 --- a/dom/media/DOMMediaStream.h +++ b/dom/media/DOMMediaStream.h @@ -833,9 +833,6 @@ class DOMHwMediaStream : public DOMLocalMediaStream { typedef mozilla::gfx::IntSize IntSize; typedef layers::OverlayImage OverlayImage; -#ifdef MOZ_WIDGET_GONK - typedef layers::OverlayImage::Data Data; -#endif public: explicit DOMHwMediaStream(nsPIDOMWindowInner* aWindow); @@ -853,14 +850,6 @@ protected: private: void Init(MediaStream* aStream, OverlayImage* aImage); - -#ifdef MOZ_WIDGET_GONK - const int DEFAULT_IMAGE_ID = 0x01; - const int DEFAULT_IMAGE_WIDTH = 400; - const int DEFAULT_IMAGE_HEIGHT = 300; - RefPtr<OverlayImage> mOverlayImage; - PrincipalHandle mPrincipalHandle; -#endif }; } // namespace mozilla diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp index 40e3b72cf..cae15eb8c 100644 --- a/dom/media/GraphDriver.cpp +++ b/dom/media/GraphDriver.cpp @@ -640,11 +640,7 @@ AudioCallbackDriver::Init() mSampleRate = output.rate = CubebUtils::PreferredSampleRate(); #if defined(__ANDROID__) -#if defined(MOZ_B2G) - output.stream_type = CubebUtils::ConvertChannelToCubebType(mAudioChannel); -#else output.stream_type = CUBEB_STREAM_TYPE_MUSIC; -#endif if (output.stream_type == CUBEB_STREAM_TYPE_MAX) { NS_WARNING("Bad stream type"); return; diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp index 4a52c22ae..94f5f32a0 100644 --- a/dom/media/MediaData.cpp +++ b/dom/media/MediaData.cpp @@ -9,9 +9,6 @@ #include "VideoUtils.h" #include "ImageContainer.h" -#ifdef MOZ_WIDGET_GONK -#include <cutils/properties.h> -#endif #include <stdint.h> namespace mozilla { @@ -93,31 +90,6 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane) aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride; } -#ifdef MOZ_WIDGET_GONK -static bool -IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane, - const VideoData::YCbCrBuffer::Plane& aCbPlane, - const VideoData::YCbCrBuffer::Plane& aCrPlane) -{ - return - aYPlane.mWidth % 2 == 0 && - aYPlane.mHeight % 2 == 0 && - aYPlane.mWidth / 2 == aCbPlane.mWidth && - aYPlane.mHeight / 2 == aCbPlane.mHeight && - aCbPlane.mWidth == aCrPlane.mWidth && - aCbPlane.mHeight == aCrPlane.mHeight; -} - -static bool -IsInEmulator() -{ - char propQemu[PROPERTY_VALUE_MAX]; - property_get("ro.kernel.qemu", propQemu, ""); - return !strncmp(propQemu, "1", 1); -} - -#endif - VideoData::VideoData(int64_t aOffset, int64_t aTime, int64_t aDuration, @@ -310,19 +282,8 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, aTimecode, aInfo.mDisplay, 0)); -#ifdef MOZ_WIDGET_GONK - const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0]; - const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1]; - const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2]; -#endif - // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR // format. -#ifdef MOZ_WIDGET_GONK - if (IsYV12Format(Y, Cb, Cr) && !IsInEmulator()) { - v->mImage = new layers::GrallocImage(); - } -#endif if (!v->mImage) { v->mImage = aContainer->CreatePlanarYCbCrImage(); } @@ -341,20 +302,6 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, return nullptr; } -#ifdef MOZ_WIDGET_GONK - if (!videoImage->IsValid() && IsYV12Format(Y, Cb, Cr)) { - // Failed to allocate gralloc. Try fallback. - v->mImage = aContainer->CreatePlanarYCbCrImage(); - if (!v->mImage) { - return nullptr; - } - videoImage = v->mImage->AsPlanarYCbCrImage(); - if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture, - true /* aCopyData */)) { - return nullptr; - } - } -#endif return v.forget(); } diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 97a6855d9..ba6b4cd47 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -13,9 +13,6 @@ #include "nsArray.h" #include "nsContentUtils.h" #include "nsHashPropertyBag.h" -#ifdef MOZ_WIDGET_GONK -#include "nsIAudioManager.h" -#endif #include "nsIEventTarget.h" #include "nsIUUIDGenerator.h" #include "nsIScriptGlobalObject.h" @@ -73,10 +70,6 @@ #include "browser_logging/WebRtcLog.h" #endif -#ifdef MOZ_B2G -#include "MediaPermissionGonk.h" -#endif - #if defined (XP_WIN) #include "mozilla/WindowsVersion.h" #include <winsock2.h> @@ -1573,7 +1566,7 @@ private: RefPtr<MediaManager> mManager; // get ref to this when creating the runnable }; -#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) +#if defined(ANDROID) class GetUserMediaRunnableWrapper : public Runnable { public: @@ -1819,10 +1812,6 @@ MediaManager::Get() { __LINE__, NS_LITERAL_STRING("Media shutdown")); MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); -#ifdef MOZ_B2G - // Init MediaPermissionManager before sending out any permission requests. - (void) MediaPermissionManager::GetInstance(); -#endif //MOZ_B2G } return sSingleton; } @@ -3050,18 +3039,6 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } return NS_OK; } -#ifdef MOZ_WIDGET_GONK - else if (!strcmp(aTopic, "phone-state-changed")) { - nsString state(aData); - nsresult rv; - uint32_t phoneState = state.ToInteger(&rv); - - if (NS_SUCCEEDED(rv) && phoneState == nsIAudioManager::PHONE_STATE_IN_CALL) { - StopMediaStreams(); - } - return NS_OK; - } -#endif return NS_OK; } diff --git a/dom/media/MediaPermissionGonk.cpp b/dom/media/MediaPermissionGonk.cpp deleted file mode 100644 index 2a9cbf331..000000000 --- a/dom/media/MediaPermissionGonk.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/* 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 "MediaManager.h" -#include "MediaPermissionGonk.h" - -#include "nsArray.h" -#include "nsCOMPtr.h" -#include "nsIContentPermissionPrompt.h" -#include "nsIDocument.h" -#include "nsIDOMNavigatorUserMedia.h" -#include "nsIStringEnumerator.h" -#include "nsJSUtils.h" -#include "nsQueryObject.h" -#include "nsPIDOMWindow.h" -#include "nsTArray.h" -#include "GetUserMediaRequest.h" -#include "mozilla/dom/PBrowserChild.h" -#include "mozilla/dom/MediaStreamTrackBinding.h" -#include "mozilla/dom/MediaStreamError.h" -#include "nsISupportsPrimitives.h" -#include "nsServiceManagerUtils.h" -#include "nsArrayUtils.h" -#include "nsContentPermissionHelper.h" -#include "mozilla/dom/PermissionMessageUtils.h" - -#define AUDIO_PERMISSION_NAME "audio-capture" -#define VIDEO_PERMISSION_NAME "video-capture" - -using namespace mozilla::dom; - -namespace mozilla { - -static MediaPermissionManager *gMediaPermMgr = nullptr; - -static void -CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices, - nsTArray<nsString> &aDeviceNameList) -{ - for (uint32_t i = 0; i < aDevices.Length(); ++i) { - nsString name; - nsresult rv = aDevices[i]->GetName(name); - NS_ENSURE_SUCCESS_VOID(rv); - aDeviceNameList.AppendElement(name); - } -} - -static already_AddRefed<nsIMediaDevice> -FindDeviceByName(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices, - const nsAString &aDeviceName) -{ - for (uint32_t i = 0; i < aDevices.Length(); ++i) { - nsCOMPtr<nsIMediaDevice> device = aDevices[i]; - nsString deviceName; - device->GetName(deviceName); - if (deviceName.Equals(aDeviceName)) { - return device.forget(); - } - } - - return nullptr; -} - -// Helper function for notifying permission granted -static nsresult -NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices) -{ - nsresult rv; - nsCOMPtr<nsIMutableArray> array = nsArray::Create(); - - for (uint32_t i = 0; i < aDevices.Length(); ++i) { - rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false); - NS_ENSURE_SUCCESS(rv, rv); - } - - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE); - - return obs->NotifyObservers(array, "getUserMedia:response:allow", - aCallID.BeginReading()); -} - -// Helper function for notifying permision denial or error -static nsresult -NotifyPermissionDeny(const nsAString &aCallID, const nsAString &aErrorMsg) -{ - nsresult rv; - nsCOMPtr<nsISupportsString> supportsString = - do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = supportsString->SetData(aErrorMsg); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE); - - return obs->NotifyObservers(supportsString, "getUserMedia:response:deny", - aCallID.BeginReading()); -} - -namespace { - -/** - * MediaPermissionRequest will send a prompt ipdl request to b2g process according - * to its owned type. - */ -class MediaPermissionRequest : public nsIContentPermissionRequest -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICONTENTPERMISSIONREQUEST - - MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest, - nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices); - - already_AddRefed<nsPIDOMWindowInner> GetOwner(); - -protected: - virtual ~MediaPermissionRequest() {} - -private: - nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice); - - bool mAudio; // Request for audio permission - bool mVideo; // Request for video permission - RefPtr<dom::GetUserMediaRequest> mRequest; - nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices - nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices - nsCOMPtr<nsIContentPermissionRequester> mRequester; -}; - -// MediaPermissionRequest -NS_IMPL_ISUPPORTS(MediaPermissionRequest, nsIContentPermissionRequest) - -MediaPermissionRequest::MediaPermissionRequest(RefPtr<dom::GetUserMediaRequest> &aRequest, - nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices) - : mRequest(aRequest) -{ - dom::MediaStreamConstraints constraints; - mRequest->GetConstraints(constraints); - - mAudio = !constraints.mAudio.IsBoolean() || constraints.mAudio.GetAsBoolean(); - mVideo = !constraints.mVideo.IsBoolean() || constraints.mVideo.GetAsBoolean(); - - for (uint32_t i = 0; i < aDevices.Length(); ++i) { - nsCOMPtr<nsIMediaDevice> device(aDevices[i]); - nsAutoString deviceType; - device->GetType(deviceType); - if (mAudio && deviceType.EqualsLiteral("audio")) { - mAudioDevices.AppendElement(device); - } - if (mVideo && deviceType.EqualsLiteral("video")) { - mVideoDevices.AppendElement(device); - } - } - - nsCOMPtr<nsPIDOMWindowInner> window = GetOwner(); - mRequester = new nsContentPermissionRequester(window); -} - -// nsIContentPermissionRequest methods -NS_IMETHODIMP -MediaPermissionRequest::GetTypes(nsIArray** aTypes) -{ - nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID); - //XXX append device list - if (mAudio) { - nsTArray<nsString> audioDeviceNames; - CreateDeviceNameList(mAudioDevices, audioDeviceNames); - nsCOMPtr<nsISupports> AudioType = - new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME), - NS_LITERAL_CSTRING("unused"), - audioDeviceNames); - types->AppendElement(AudioType, false); - } - if (mVideo) { - nsTArray<nsString> videoDeviceNames; - CreateDeviceNameList(mVideoDevices, videoDeviceNames); - nsCOMPtr<nsISupports> VideoType = - new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME), - NS_LITERAL_CSTRING("unused"), - videoDeviceNames); - types->AppendElement(VideoType, false); - } - NS_IF_ADDREF(*aTypes = types); - - return NS_OK; -} - -NS_IMETHODIMP -MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal) -{ - NS_ENSURE_ARG_POINTER(aRequestingPrincipal); - - nsCOMPtr<nsPIDOMWindowInner> window = - nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner(); - NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); - - nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); - NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); - - NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal()); - return NS_OK; -} - -NS_IMETHODIMP -MediaPermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow) -{ - NS_ENSURE_ARG_POINTER(aRequestingWindow); - nsCOMPtr<nsPIDOMWindowInner> window = - nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner(); - window.forget(aRequestingWindow); - return NS_OK; -} - -NS_IMETHODIMP -MediaPermissionRequest::GetElement(nsIDOMElement** aRequestingElement) -{ - NS_ENSURE_ARG_POINTER(aRequestingElement); - *aRequestingElement = nullptr; - return NS_OK; -} - -NS_IMETHODIMP -MediaPermissionRequest::Cancel() -{ - nsString callID; - mRequest->GetCallID(callID); - NotifyPermissionDeny(callID, NS_LITERAL_STRING("SecurityError")); - return NS_OK; -} - -NS_IMETHODIMP -MediaPermissionRequest::Allow(JS::HandleValue aChoices) -{ - // check if JS object - if (!aChoices.isObject()) { - MOZ_ASSERT(false, "Not a correct format of PermissionChoice"); - return NS_ERROR_INVALID_ARG; - } - // iterate through audio-capture and video-capture - AutoJSAPI jsapi; - if (!jsapi.Init(&aChoices.toObject())) { - return NS_ERROR_UNEXPECTED; - } - JSContext* cx = jsapi.cx(); - JS::Rooted<JSObject*> obj(cx, &aChoices.toObject()); - JS::Rooted<JS::Value> v(cx); - - // get selected audio device name - nsString audioDevice; - if (mAudio) { - if (!JS_GetProperty(cx, obj, AUDIO_PERMISSION_NAME, &v) || !v.isString()) { - return NS_ERROR_FAILURE; - } - nsAutoJSString deviceName; - if (!deviceName.init(cx, v)) { - MOZ_ASSERT(false, "Couldn't initialize string from aChoices"); - return NS_ERROR_FAILURE; - } - audioDevice = deviceName; - } - - // get selected video device name - nsString videoDevice; - if (mVideo) { - if (!JS_GetProperty(cx, obj, VIDEO_PERMISSION_NAME, &v) || !v.isString()) { - return NS_ERROR_FAILURE; - } - nsAutoJSString deviceName; - if (!deviceName.init(cx, v)) { - MOZ_ASSERT(false, "Couldn't initialize string from aChoices"); - return NS_ERROR_FAILURE; - } - videoDevice = deviceName; - } - - return DoAllow(audioDevice, videoDevice); -} - -NS_IMETHODIMP -MediaPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester) -{ - NS_ENSURE_ARG_POINTER(aRequester); - - nsCOMPtr<nsIContentPermissionRequester> requester = mRequester; - requester.forget(aRequester); - return NS_OK; -} - -nsresult -MediaPermissionRequest::DoAllow(const nsString &audioDevice, - const nsString &videoDevice) -{ - nsTArray<nsCOMPtr<nsIMediaDevice> > selectedDevices; - if (mAudio) { - nsCOMPtr<nsIMediaDevice> device = - FindDeviceByName(mAudioDevices, audioDevice); - if (device) { - selectedDevices.AppendElement(device); - } - } - - if (mVideo) { - nsCOMPtr<nsIMediaDevice> device = - FindDeviceByName(mVideoDevices, videoDevice); - if (device) { - selectedDevices.AppendElement(device); - } - } - - nsString callID; - mRequest->GetCallID(callID); - return NotifyPermissionAllow(callID, selectedDevices); -} - -already_AddRefed<nsPIDOMWindowInner> -MediaPermissionRequest::GetOwner() -{ - nsCOMPtr<nsPIDOMWindowInner> window = - nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID())->AsInner(); - return window.forget(); -} - -// Success callback for MediaManager::GetUserMediaDevices(). -class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK - - explicit MediaDeviceSuccessCallback(RefPtr<dom::GetUserMediaRequest> &aRequest) - : mRequest(aRequest) {} - -protected: - virtual ~MediaDeviceSuccessCallback() {} - -private: - nsresult DoPrompt(RefPtr<MediaPermissionRequest> &req); - RefPtr<dom::GetUserMediaRequest> mRequest; -}; - -NS_IMPL_ISUPPORTS(MediaDeviceSuccessCallback, nsIGetUserMediaDevicesSuccessCallback) - -// nsIGetUserMediaDevicesSuccessCallback method -NS_IMETHODIMP -MediaDeviceSuccessCallback::OnSuccess(nsIVariant* aDevices) -{ - nsIID elementIID; - uint16_t elementType; - void* rawArray; - uint32_t arrayLen; - - nsresult rv; - rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray); - NS_ENSURE_SUCCESS(rv, rv); - - if (elementType != nsIDataType::VTYPE_INTERFACE) { - free(rawArray); - return NS_ERROR_FAILURE; - } - - // Create array for nsIMediaDevice - nsTArray<nsCOMPtr<nsIMediaDevice> > devices; - - nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray); - for (uint32_t i = 0; i < arrayLen; ++i) { - nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i])); - devices.AppendElement(device); - NS_IF_RELEASE(supportsArray[i]); // explicitly decrease reference count for raw pointer - } - free(rawArray); // explicitly free for the memory from nsIVariant::GetAsArray - - // Send MediaPermissionRequest - RefPtr<MediaPermissionRequest> req = new MediaPermissionRequest(mRequest, devices); - rv = DoPrompt(req); - - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -// Trigger permission prompt UI -nsresult -MediaDeviceSuccessCallback::DoPrompt(RefPtr<MediaPermissionRequest> &req) -{ - nsCOMPtr<nsPIDOMWindowInner> window(req->GetOwner()); - return dom::nsContentPermissionUtils::AskPermission(req, window); -} - -// Error callback for MediaManager::GetUserMediaDevices() -class MediaDeviceErrorCallback: public nsIDOMGetUserMediaErrorCallback -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK - - explicit MediaDeviceErrorCallback(const nsAString &aCallID) - : mCallID(aCallID) {} - -protected: - virtual ~MediaDeviceErrorCallback() {} - -private: - const nsString mCallID; -}; - -NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback) - -// nsIDOMGetUserMediaErrorCallback method -NS_IMETHODIMP -MediaDeviceErrorCallback::OnError(nsISupports* aError) -{ - RefPtr<MediaStreamError> error = do_QueryObject(aError); - if (!error) { - return NS_ERROR_NO_INTERFACE; - } - - nsString name; - error->GetName(name); - return NotifyPermissionDeny(mCallID, name); -} - -} // namespace anonymous - -// MediaPermissionManager -NS_IMPL_ISUPPORTS(MediaPermissionManager, nsIObserver) - -MediaPermissionManager* -MediaPermissionManager::GetInstance() -{ - if (!gMediaPermMgr) { - gMediaPermMgr = new MediaPermissionManager(); - } - - return gMediaPermMgr; -} - -MediaPermissionManager::MediaPermissionManager() -{ - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - if (obs) { - obs->AddObserver(this, "getUserMedia:request", false); - obs->AddObserver(this, "xpcom-shutdown", false); - } -} - -MediaPermissionManager::~MediaPermissionManager() -{ - this->Deinit(); -} - -nsresult -MediaPermissionManager::Deinit() -{ - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - if (obs) { - obs->RemoveObserver(this, "getUserMedia:request"); - obs->RemoveObserver(this, "xpcom-shutdown"); - } - return NS_OK; -} - -// nsIObserver method -NS_IMETHODIMP -MediaPermissionManager::Observe(nsISupports* aSubject, const char* aTopic, - const char16_t* aData) -{ - nsresult rv; - if (!strcmp(aTopic, "getUserMedia:request")) { - RefPtr<dom::GetUserMediaRequest> req = - static_cast<dom::GetUserMediaRequest*>(aSubject); - rv = HandleRequest(req); - - if (NS_FAILED(rv)) { - nsString callID; - req->GetCallID(callID); - NotifyPermissionDeny(callID, NS_LITERAL_STRING("unable to enumerate media device")); - } - } else if (!strcmp(aTopic, "xpcom-shutdown")) { - rv = this->Deinit(); - } else { - // not reachable - rv = NS_ERROR_FAILURE; - } - return rv; -} - -// Handle GetUserMediaRequest, query available media device first. -nsresult -MediaPermissionManager::HandleRequest(RefPtr<dom::GetUserMediaRequest> &req) -{ - nsString callID; - req->GetCallID(callID); - uint64_t innerWindowID = req->InnerWindowID(); - - nsCOMPtr<nsPIDOMWindowInner> innerWindow = - nsGlobalWindow::GetInnerWindowWithId(innerWindowID)->AsInner(); - if (!innerWindow) { - MOZ_ASSERT(false, "No inner window"); - return NS_ERROR_FAILURE; - } - - nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess = - new MediaDeviceSuccessCallback(req); - nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError = - new MediaDeviceErrorCallback(callID); - - dom::MediaStreamConstraints constraints; - req->GetConstraints(constraints); - - RefPtr<MediaManager> MediaMgr = MediaManager::GetInstance(); - nsresult rv = MediaMgr->GetUserMediaDevices(innerWindow, constraints, - onSuccess, onError, - innerWindowID, callID); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -} // namespace mozilla diff --git a/dom/media/MediaPermissionGonk.h b/dom/media/MediaPermissionGonk.h deleted file mode 100644 index 0a2fac056..000000000 --- a/dom/media/MediaPermissionGonk.h +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 DOM_MEDIA_MEDIAPERMISSIONGONK_H -#define DOM_MEDIA_MEDIAPERMISSIONGONK_H - -#include "nsError.h" -#include "nsIObserver.h" -#include "nsISupportsImpl.h" -#include "GetUserMediaRequest.h" - -namespace mozilla { - -/** - * The observer to create the MediaPermissionMgr. This is the entry point of - * permission request on b2g. - */ -class MediaPermissionManager : public nsIObserver -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - static MediaPermissionManager* GetInstance(); - -protected: - virtual ~MediaPermissionManager(); - -private: - MediaPermissionManager(); - nsresult Deinit(); - nsresult HandleRequest(RefPtr<dom::GetUserMediaRequest> &req); -}; - -} // namespace mozilla - -#endif // DOM_MEDIA_MEDIAPERMISSIONGONK_H - diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index 98b8debbe..0c3021799 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -791,7 +791,6 @@ RTCPeerConnection.prototype = { return this._havePermission; } if (this._isChrome || - AppConstants.MOZ_B2G || Services.prefs.getBoolPref("media.navigator.permission.disabled")) { return this._havePermission = Promise.resolve(); } diff --git a/dom/media/android/AndroidMediaPluginHost.cpp b/dom/media/android/AndroidMediaPluginHost.cpp index d3dce2b93..cc3adbbd3 100644 --- a/dom/media/android/AndroidMediaPluginHost.cpp +++ b/dom/media/android/AndroidMediaPluginHost.cpp @@ -22,7 +22,7 @@ #include "nsIPropertyBag2.h" -#if defined(ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(ANDROID) #include "android/log.h" #define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidMediaPluginHost" , ## args) #else @@ -134,7 +134,7 @@ static bool IsOmxSupported() // nullptr is returned if Omx decoding is not supported on the device, static const char* GetOmxLibraryName() { -#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) +#if defined(ANDROID) nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1"); NS_ASSERTION(infoService, "Could not find a system info service"); @@ -172,7 +172,7 @@ static const char* GetOmxLibraryName() if (!IsOmxSupported()) return nullptr; -#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) +#if defined(ANDROID) if (version >= 17) { return "libomxpluginkk.so"; } @@ -180,8 +180,6 @@ static const char* GetOmxLibraryName() // Ice Cream Sandwich and Jellybean return "libomxplugin.so"; -#elif defined(ANDROID) && defined(MOZ_WIDGET_GONK) - return "libomxplugin.so"; #else return nullptr; #endif diff --git a/dom/media/encoder/OpusTrackEncoder.cpp b/dom/media/encoder/OpusTrackEncoder.cpp index c65d57788..4b55b3954 100644 --- a/dom/media/encoder/OpusTrackEncoder.cpp +++ b/dom/media/encoder/OpusTrackEncoder.cpp @@ -9,12 +9,7 @@ #include <opus/opus.h> #undef LOG -#ifdef MOZ_WIDGET_GONK -#include <android/log.h> -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args); -#else #define LOG(args, ...) -#endif namespace mozilla { diff --git a/dom/media/encoder/TrackEncoder.cpp b/dom/media/encoder/TrackEncoder.cpp index ea39bb5a6..df6b24409 100644 --- a/dom/media/encoder/TrackEncoder.cpp +++ b/dom/media/encoder/TrackEncoder.cpp @@ -10,12 +10,7 @@ #include "VideoUtils.h" #undef LOG -#ifdef MOZ_WIDGET_GONK -#include <android/log.h> -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args); -#else #define LOG(args, ...) -#endif namespace mozilla { diff --git a/dom/media/encoder/fmp4_muxer/AMRBox.cpp b/dom/media/encoder/fmp4_muxer/AMRBox.cpp deleted file mode 100644 index cd1a34fae..000000000 --- a/dom/media/encoder/fmp4_muxer/AMRBox.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "AMRBox.h" -#include "ISOTrackMetadata.h" - -namespace mozilla { - -nsresult -AMRSampleEntry::Generate(uint32_t* aBoxSize) -{ - uint32_t box_size; - nsresult rv = amr_special_box->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - - *aBoxSize = size; - return NS_OK; -} - -nsresult -AMRSampleEntry::Write() -{ - BoxSizeChecker checker(mControl, size); - nsresult rv; - rv = AudioSampleEntry::Write(); - NS_ENSURE_SUCCESS(rv, rv); - rv = amr_special_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -AMRSampleEntry::AMRSampleEntry(ISOControl* aControl) - : AudioSampleEntry(NS_LITERAL_CSTRING("samr"), aControl) -{ - amr_special_box = new AMRSpecificBox(aControl); - MOZ_COUNT_CTOR(AMRSampleEntry); -} - -AMRSampleEntry::~AMRSampleEntry() -{ - MOZ_COUNT_DTOR(AMRSampleEntry); -} - -nsresult -AMRSpecificBox::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - FragmentBuffer* frag = mControl->GetFragment(Audio_Track); - rv = frag->GetCSD(amrDecSpecInfo); - NS_ENSURE_SUCCESS(rv, rv); - - size += amrDecSpecInfo.Length(); - *aBoxSize = size; - - return NS_OK; -} - -nsresult -AMRSpecificBox::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - mControl->Write(amrDecSpecInfo.Elements(), amrDecSpecInfo.Length()); - return NS_OK; -} - -AMRSpecificBox::AMRSpecificBox(ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("damr"), aControl) -{ - MOZ_COUNT_CTOR(AMRSpecificBox); -} - -AMRSpecificBox::~AMRSpecificBox() -{ - MOZ_COUNT_DTOR(AMRSpecificBox); -} - -} diff --git a/dom/media/encoder/fmp4_muxer/AMRBox.h b/dom/media/encoder/fmp4_muxer/AMRBox.h deleted file mode 100644 index 645d7f89c..000000000 --- a/dom/media/encoder/fmp4_muxer/AMRBox.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 AMRBOX_h_ -#define AMRBOX_h_ - -#include "nsTArray.h" -#include "MuxerOperation.h" - -namespace mozilla { - -class ISOControl; - -// 3GPP TS 26.244 6.7 'AMRSpecificBox field for AMRSampleEntry box' -// Box type: 'damr' -class AMRSpecificBox : public Box { -public: - // 3GPP members - nsTArray<uint8_t> amrDecSpecInfo; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // AMRSpecificBox methods - AMRSpecificBox(ISOControl* aControl); - ~AMRSpecificBox(); -}; - -// 3GPP TS 26.244 6.5 'AMRSampleEntry box' -// Box type: 'sawb' -class AMRSampleEntry : public AudioSampleEntry { -public: - // 3GPP members - RefPtr<AMRSpecificBox> amr_special_box; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // AMRSampleEntry methods - AMRSampleEntry(ISOControl* aControl); - ~AMRSampleEntry(); -}; - -} - -#endif // AMRBOX_h_ diff --git a/dom/media/encoder/fmp4_muxer/AVCBox.cpp b/dom/media/encoder/fmp4_muxer/AVCBox.cpp deleted file mode 100644 index a45cda8b7..000000000 --- a/dom/media/encoder/fmp4_muxer/AVCBox.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 <climits> -#include "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "AVCBox.h" - -namespace mozilla { - -nsresult -AVCSampleEntry::Generate(uint32_t* aBoxSize) -{ - uint32_t avc_box_size = 0; - nsresult rv; - rv = avcConfigBox->Generate(&avc_box_size); - NS_ENSURE_SUCCESS(rv, rv); - - size += avc_box_size; - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -AVCSampleEntry::Write() -{ - BoxSizeChecker checker(mControl, size); - nsresult rv; - rv = VisualSampleEntry::Write(); - NS_ENSURE_SUCCESS(rv, rv); - rv = avcConfigBox->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -AVCSampleEntry::AVCSampleEntry(ISOControl* aControl) - : VisualSampleEntry(NS_LITERAL_CSTRING("avc1"), aControl) -{ - avcConfigBox = new AVCConfigurationBox(aControl); - MOZ_COUNT_CTOR(AVCSampleEntry); -} - -AVCSampleEntry::~AVCSampleEntry() -{ - MOZ_COUNT_DTOR(AVCSampleEntry); -} - -AVCConfigurationBox::AVCConfigurationBox(ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("avcC"), aControl) -{ - MOZ_COUNT_CTOR(AVCConfigurationBox); -} - -AVCConfigurationBox::~AVCConfigurationBox() -{ - MOZ_COUNT_DTOR(AVCConfigurationBox); -} - -nsresult -AVCConfigurationBox::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - FragmentBuffer* frag = mControl->GetFragment(Video_Track); - rv = frag->GetCSD(avcConfig); - NS_ENSURE_SUCCESS(rv, rv); - size += avcConfig.Length(); - *aBoxSize = size; - return NS_OK; -} - -nsresult -AVCConfigurationBox::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - - mControl->Write(avcConfig.Elements(), avcConfig.Length()); - - return NS_OK; -} - -} diff --git a/dom/media/encoder/fmp4_muxer/AVCBox.h b/dom/media/encoder/fmp4_muxer/AVCBox.h deleted file mode 100644 index 9640d9e8f..000000000 --- a/dom/media/encoder/fmp4_muxer/AVCBox.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 AVCBox_h_ -#define AVCBox_h_ - -#include "nsTArray.h" -#include "ISOMediaBoxes.h" - -namespace mozilla { - -class ISOControl; - -// 14496-12 8.5.2.2 -#define resolution_72_dpi 0x00480000 -#define video_depth 0x0018 - -// 14496-15 5.3.4.1 'Sample description name and format' -// Box type: 'avcC' -class AVCConfigurationBox : public Box { -public: - // ISO BMFF members - - // avcConfig is CodecSpecificData from 14496-15 '5.3.4.1 Sample description - // name and format. - // These data are generated by encoder and we encapsulated the generated - // bitstream into box directly. - nsTArray<uint8_t> avcConfig; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // AVCConfigurationBox methods - AVCConfigurationBox(ISOControl* aControl); - ~AVCConfigurationBox(); -}; - -// 14496-15 5.3.4.1 'Sample description name and format' -// Box type: 'avc1' -class AVCSampleEntry : public VisualSampleEntry { -public: - // ISO BMFF members - RefPtr<AVCConfigurationBox> avcConfigBox; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // VisualSampleEntry methods - AVCSampleEntry(ISOControl* aControl); - ~AVCSampleEntry(); -}; - -} - -#endif // AVCBox_h_ diff --git a/dom/media/encoder/fmp4_muxer/EVRCBox.cpp b/dom/media/encoder/fmp4_muxer/EVRCBox.cpp deleted file mode 100644 index 096e4013d..000000000 --- a/dom/media/encoder/fmp4_muxer/EVRCBox.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "EVRCBox.h" -#include "ISOTrackMetadata.h" - -namespace mozilla { - -nsresult -EVRCSampleEntry::Generate(uint32_t* aBoxSize) -{ - uint32_t box_size; - nsresult rv = evrc_special_box->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - - *aBoxSize = size; - return NS_OK; -} - -nsresult -EVRCSampleEntry::Write() -{ - BoxSizeChecker checker(mControl, size); - nsresult rv; - rv = AudioSampleEntry::Write(); - NS_ENSURE_SUCCESS(rv, rv); - rv = evrc_special_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -EVRCSampleEntry::EVRCSampleEntry(ISOControl* aControl) - : AudioSampleEntry(NS_LITERAL_CSTRING("sevc"), aControl) -{ - evrc_special_box = new EVRCSpecificBox(aControl); - MOZ_COUNT_CTOR(EVRCSampleEntry); -} - -EVRCSampleEntry::~EVRCSampleEntry() -{ - MOZ_COUNT_DTOR(EVRCSampleEntry); -} - -nsresult -EVRCSpecificBox::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - FragmentBuffer* frag = mControl->GetFragment(Audio_Track); - rv = frag->GetCSD(evrcDecSpecInfo); - NS_ENSURE_SUCCESS(rv, rv); - - size += evrcDecSpecInfo.Length(); - *aBoxSize = size; - - return NS_OK; -} - -nsresult -EVRCSpecificBox::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - mControl->Write(evrcDecSpecInfo.Elements(), evrcDecSpecInfo.Length()); - return NS_OK; -} - -EVRCSpecificBox::EVRCSpecificBox(ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("devc"), aControl) -{ - MOZ_COUNT_CTOR(EVRCSpecificBox); -} - -EVRCSpecificBox::~EVRCSpecificBox() -{ - MOZ_COUNT_DTOR(EVRCSpecificBox); -} - -} diff --git a/dom/media/encoder/fmp4_muxer/EVRCBox.h b/dom/media/encoder/fmp4_muxer/EVRCBox.h deleted file mode 100644 index 31355849a..000000000 --- a/dom/media/encoder/fmp4_muxer/EVRCBox.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 EVRCBOX_h_ -#define EVRCBOX_h_ - -#include "nsTArray.h" -#include "MuxerOperation.h" - -namespace mozilla { - -class ISOControl; - -// 3GPP TS 26.244 6.7 'EVRCSpecificBox field for EVRCSampleEntry box' -// Box type: 'devc' -class EVRCSpecificBox : public Box { -public: - // 3GPP members - nsTArray<uint8_t> evrcDecSpecInfo; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // EVRCSpecificBox methods - EVRCSpecificBox(ISOControl* aControl); - ~EVRCSpecificBox(); -}; - -// 3GPP TS 26.244 6.5 'EVRCSampleEntry box' -// Box type: 'sevc' -class EVRCSampleEntry : public AudioSampleEntry { -public: - // 3GPP members - RefPtr<EVRCSpecificBox> evrc_special_box; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // EVRCSampleEntry methods - EVRCSampleEntry(ISOControl* aControl); - ~EVRCSampleEntry(); -}; - -} - -#endif // EVRCBOX_h_ diff --git a/dom/media/encoder/fmp4_muxer/ISOControl.cpp b/dom/media/encoder/fmp4_muxer/ISOControl.cpp deleted file mode 100644 index 6addaeb30..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOControl.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 <time.h> -#include "nsAutoPtr.h" -#include "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "EncodedFrameContainer.h" - -namespace mozilla { - -// For MP4 creation_time and modification_time offset from January 1, 1904 to -// January 1, 1970. -#define iso_time_offset 2082844800 - -FragmentBuffer::FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration) - : mTrackType(aTrackType) - , mFragDuration(aFragDuration) - , mMediaStartTime(0) - , mFragmentNumber(0) - , mLastFrameTimeOfLastFragment(0) - , mEOS(false) -{ - mFragArray.AppendElement(); - MOZ_COUNT_CTOR(FragmentBuffer); -} - -FragmentBuffer::~FragmentBuffer() -{ - MOZ_COUNT_DTOR(FragmentBuffer); -} - -bool -FragmentBuffer::HasEnoughData() -{ - // Audio or video frame is enough to form a moof. - return (mFragArray.Length() > 1); -} - -nsresult -FragmentBuffer::GetCSD(nsTArray<uint8_t>& aCSD) -{ - if (!mCSDFrame) { - return NS_ERROR_FAILURE; - } - aCSD.AppendElements(mCSDFrame->GetFrameData().Elements(), - mCSDFrame->GetFrameData().Length()); - - return NS_OK; -} - -nsresult -FragmentBuffer::AddFrame(EncodedFrame* aFrame) -{ - // already EOS, it rejects all new data. - if (mEOS) { - MOZ_ASSERT(0); - return NS_OK; - } - - EncodedFrame::FrameType type = aFrame->GetFrameType(); - if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD || - type == EncodedFrame::AMR_AUDIO_CSD || type == EncodedFrame::EVRC_AUDIO_CSD) { - mCSDFrame = aFrame; - // Use CSD's timestamp as the start time. Encoder should send CSD frame first - // and then data frames. - mMediaStartTime = aFrame->GetTimeStamp(); - mFragmentNumber = 1; - return NS_OK; - } - - // if the timestamp is incorrect, abort it. - if (aFrame->GetTimeStamp() < mMediaStartTime) { - MOZ_ASSERT(false); - return NS_ERROR_FAILURE; - } - - mFragArray.LastElement().AppendElement(aFrame); - - // check if current fragment is reach the fragment duration. - if ((aFrame->GetTimeStamp() - mMediaStartTime) >= (mFragDuration * mFragmentNumber)) { - mFragArray.AppendElement(); - mFragmentNumber++; - } - - return NS_OK; -} - -nsresult -FragmentBuffer::GetFirstFragment(nsTArray<RefPtr<EncodedFrame>>& aFragment, - bool aFlush) -{ - // It should be called only if there is a complete fragment in mFragArray. - if (mFragArray.Length() <= 1 && !mEOS) { - MOZ_ASSERT(false); - return NS_ERROR_FAILURE; - } - - if (aFlush) { - aFragment.SwapElements(mFragArray.ElementAt(0)); - mFragArray.RemoveElementAt(0); - } else { - aFragment.AppendElements(mFragArray.ElementAt(0)); - } - return NS_OK; -} - -uint32_t -FragmentBuffer::GetFirstFragmentSampleNumber() -{ - return mFragArray.ElementAt(0).Length(); -} - -uint32_t -FragmentBuffer::GetFirstFragmentSampleSize() -{ - uint32_t size = 0; - uint32_t len = mFragArray.ElementAt(0).Length(); - for (uint32_t i = 0; i < len; i++) { - size += mFragArray.ElementAt(0).ElementAt(i)->GetFrameData().Length(); - } - return size; -} - -ISOControl::ISOControl(uint32_t aMuxingType) - : mMuxingType(aMuxingType) - , mAudioFragmentBuffer(nullptr) - , mVideoFragmentBuffer(nullptr) - , mFragNum(0) - , mOutputSize(0) - , mBitCount(0) - , mBit(0) -{ - // Create a data array for first mp4 Box, ftyp. - mOutBuffers.SetLength(1); - MOZ_COUNT_CTOR(ISOControl); -} - -ISOControl::~ISOControl() -{ - MOZ_COUNT_DTOR(ISOControl); -} - -uint32_t -ISOControl::GetNextTrackID() -{ - return (mMetaArray.Length() + 1); -} - -uint32_t -ISOControl::GetTrackID(TrackMetadataBase::MetadataKind aKind) -{ - for (uint32_t i = 0; i < mMetaArray.Length(); i++) { - if (mMetaArray[i]->GetKind() == aKind) { - return (i + 1); - } - } - - // Track ID shouldn't be 0. It must be something wrong here. - MOZ_ASSERT(0); - return 0; -} - -nsresult -ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta) -{ - if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC || - aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR || - aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC || - aTrackMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) { - mMetaArray.AppendElement(aTrackMeta); - return NS_OK; - } - return NS_ERROR_FAILURE; -} - -nsresult -ISOControl::GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta) -{ - for (uint32_t i = 0; i < mMetaArray.Length() ; i++) { - if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC || - mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR || - mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_EVRC) { - aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get()); - return NS_OK; - } - } - return NS_ERROR_FAILURE; -} - -nsresult -ISOControl::GetVideoMetadata(RefPtr<VideoTrackMetadata>& aVidMeta) -{ - for (uint32_t i = 0; i < mMetaArray.Length() ; i++) { - if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AVC) { - aVidMeta = static_cast<VideoTrackMetadata*>(mMetaArray[i].get()); - return NS_OK; - } - } - return NS_ERROR_FAILURE; -} - -bool -ISOControl::HasAudioTrack() -{ - RefPtr<AudioTrackMetadata> audMeta; - GetAudioMetadata(audMeta); - return audMeta; -} - -bool -ISOControl::HasVideoTrack() -{ - RefPtr<VideoTrackMetadata> vidMeta; - GetVideoMetadata(vidMeta); - return vidMeta; -} - -nsresult -ISOControl::SetFragment(FragmentBuffer* aFragment) -{ - if (aFragment->GetType() == Audio_Track) { - mAudioFragmentBuffer = aFragment; - } else { - mVideoFragmentBuffer = aFragment; - } - return NS_OK; -} - -FragmentBuffer* -ISOControl::GetFragment(uint32_t aType) -{ - if (aType == Audio_Track) { - return mAudioFragmentBuffer; - } else if (aType == Video_Track){ - return mVideoFragmentBuffer; - } - MOZ_ASSERT(0); - return nullptr; -} - -nsresult -ISOControl::GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs) -{ - uint32_t len = mOutBuffers.Length(); - for (uint32_t i = 0; i < len; i++) { - mOutBuffers[i].SwapElements(*aOutputBufs->AppendElement()); - } - return FlushBuf(); -} - -nsresult -ISOControl::FlushBuf() -{ - mOutBuffers.SetLength(1); - return NS_OK; -} - -uint32_t -ISOControl::WriteAVData(nsTArray<uint8_t>& aArray) -{ - MOZ_ASSERT(!mBitCount); - - uint32_t len = aArray.Length(); - if (!len) { - return 0; - } - - mOutputSize += len; - - // The last element already has data, allocated a new element for pointer - // swapping. - if (mOutBuffers.LastElement().Length()) { - mOutBuffers.AppendElement(); - } - // Swap the video/audio data pointer. - mOutBuffers.LastElement().SwapElements(aArray); - // Following data could be boxes, so appending a new uint8_t array here. - mOutBuffers.AppendElement(); - - return len; -} - -uint32_t -ISOControl::WriteBits(uint64_t aBits, size_t aNumBits) -{ - uint8_t output_byte = 0; - - MOZ_ASSERT(aNumBits <= 64); - // TODO: rewritten following with bitset? - for (size_t i = aNumBits; i > 0; i--) { - mBit |= (((aBits >> (i - 1)) & 1) << (8 - ++mBitCount)); - if (mBitCount == 8) { - Write(&mBit, sizeof(uint8_t)); - mBit = 0; - mBitCount = 0; - output_byte++; - } - } - return output_byte; -} - -uint32_t -ISOControl::Write(uint8_t* aBuf, uint32_t aSize) -{ - mOutBuffers.LastElement().AppendElements(aBuf, aSize); - mOutputSize += aSize; - return aSize; -} - -uint32_t -ISOControl::Write(uint8_t aData) -{ - MOZ_ASSERT(!mBitCount); - Write((uint8_t*)&aData, sizeof(uint8_t)); - return sizeof(uint8_t); -} - -uint32_t -ISOControl::GetBufPos() -{ - uint32_t len = mOutBuffers.Length(); - uint32_t pos = 0; - for (uint32_t i = 0; i < len; i++) { - pos += mOutBuffers.ElementAt(i).Length(); - } - return pos; -} - -uint32_t -ISOControl::WriteFourCC(const char* aType) -{ - // Bit operation should be aligned to byte before writing any byte data. - MOZ_ASSERT(!mBitCount); - - uint32_t size = strlen(aType); - if (size == 4) { - return Write((uint8_t*)aType, size); - } - - return 0; -} - -nsresult -ISOControl::GenerateFtyp() -{ - nsresult rv; - uint32_t size; - nsAutoPtr<FileTypeBox> type_box(new FileTypeBox(this)); - rv = type_box->Generate(&size); - NS_ENSURE_SUCCESS(rv, rv); - rv = type_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -nsresult -ISOControl::GenerateMoov() -{ - nsresult rv; - uint32_t size; - nsAutoPtr<MovieBox> moov_box(new MovieBox(this)); - rv = moov_box->Generate(&size); - NS_ENSURE_SUCCESS(rv, rv); - rv = moov_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -nsresult -ISOControl::GenerateMoof(uint32_t aTrackType) -{ - mFragNum++; - - nsresult rv; - uint32_t size; - uint64_t first_sample_offset = mOutputSize; - nsAutoPtr<MovieFragmentBox> moof_box(new MovieFragmentBox(aTrackType, this)); - nsAutoPtr<MediaDataBox> mdat_box(new MediaDataBox(aTrackType, this)); - - rv = moof_box->Generate(&size); - NS_ENSURE_SUCCESS(rv, rv); - first_sample_offset += size; - rv = mdat_box->Generate(&size); - NS_ENSURE_SUCCESS(rv, rv); - first_sample_offset += mdat_box->FirstSampleOffsetInMediaDataBox(); - - // correct offset info - nsTArray<RefPtr<MuxerOperation>> tfhds; - rv = moof_box->Find(NS_LITERAL_CSTRING("tfhd"), tfhds); - NS_ENSURE_SUCCESS(rv, rv); - uint32_t len = tfhds.Length(); - for (uint32_t i = 0; i < len; i++) { - TrackFragmentHeaderBox* tfhd = (TrackFragmentHeaderBox*) tfhds.ElementAt(i).get(); - rv = tfhd->UpdateBaseDataOffset(first_sample_offset); - NS_ENSURE_SUCCESS(rv, rv); - } - - rv = moof_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - rv = mdat_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -uint32_t -ISOControl::GetTime() -{ - return (uint64_t)time(nullptr) + iso_time_offset; -} - -} diff --git a/dom/media/encoder/fmp4_muxer/ISOControl.h b/dom/media/encoder/fmp4_muxer/ISOControl.h deleted file mode 100644 index 3c445caee..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOControl.h +++ /dev/null @@ -1,250 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 ISOCOMPOSITOR_H_ -#define ISOCOMPOSITOR_H_ - -#include "mozilla/EndianUtils.h" -#include "nsTArray.h" -#include "ISOTrackMetadata.h" -#include "EncodedFrameContainer.h" - -namespace mozilla { - -class Box; -class ISOControl; - -/** - * This class collects elementary stream data to form a fragment. - * ISOMediaWriter will check if the data is enough; if yes, the corresponding - * moof will be created and write to ISOControl. - * Each audio and video has its own fragment and only one during the whole - * life cycle, when a fragment is formed in ISOControl, Flush() needs to - * be called to reset it. - */ -class FragmentBuffer { -public: - // aTrackType: it could be Audio_Track or Video_Track. - // aFragDuration: it is the fragment duration. (microsecond per unit) - // Audio and video have the same fragment duration. - FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration); - ~FragmentBuffer(); - - // Get samples of first fragment, that will swap all the elements in the - // mFragArray[0] when aFlush = true, and caller is responsible for drop - // EncodedFrame reference count. - nsresult GetFirstFragment(nsTArray<RefPtr<EncodedFrame>>& aFragment, - bool aFlush = false); - - // Add sample frame to the last element fragment of mFragArray. If sample - // number is enough, it will append a new fragment element. And the new - // sample will be added to the new fragment element of mFragArray. - nsresult AddFrame(EncodedFrame* aFrame); - - // Get total sample size of first complete fragment size. - uint32_t GetFirstFragmentSampleSize(); - - // Get sample number of first complete fragment. - uint32_t GetFirstFragmentSampleNumber(); - - // Check if it accumulates enough frame data. - // It returns true when data is enough to form a fragment. - bool HasEnoughData(); - - // Called by ISOMediaWriter when TrackEncoder has sent the last frame. The - // remains frame data will form the last moof and move the state machine to - // in ISOMediaWriter to last phrase. - nsresult SetEndOfStream() { - mEOS = true; - return NS_OK; - } - bool EOS() { return mEOS; } - - // CSD (codec specific data), it is generated by encoder and the data depends - // on codec type. This data will be sent as a special frame from encoder to - // ISOMediaWriter and pass to this class via AddFrame(). - nsresult GetCSD(nsTArray<uint8_t>& aCSD); - - bool HasCSD() { return mCSDFrame; } - - uint32_t GetType() { return mTrackType; } - - void SetLastFragmentLastFrameTime(uint32_t aTime) { - mLastFrameTimeOfLastFragment = aTime; - } - - uint32_t GetLastFragmentLastFrameTime() { - return mLastFrameTimeOfLastFragment; - } - -private: - uint32_t mTrackType; - - // Fragment duration, microsecond per unit. - uint32_t mFragDuration; - - // Media start time, microsecond per unit. - // Together with mFragDuration, mFragmentNumber and EncodedFrame->GetTimeStamp(), - // when the difference between current frame time and mMediaStartTime is - // exceeded current fragment ceiling timeframe, that means current fragment has - // enough data and a new element in mFragArray will be added. - uint64_t mMediaStartTime; - - // Current fragment number. It will be increase when a new element of - // mFragArray is created. - // Note: - // It only means the fragment number of current accumulated frames, not - // the current 'creating' fragment mFragNum in ISOControl. - uint32_t mFragmentNumber; - - // The last frame time stamp of last fragment. It is for calculating the - // play duration of first frame in current fragment. The frame duration is - // defined as "current frame timestamp - last frame timestamp" here. So it - // needs to keep the last timestamp of last fragment. - uint32_t mLastFrameTimeOfLastFragment; - - // Array of fragments, each element has enough samples to form a - // complete fragment. - nsTArray<nsTArray<RefPtr<EncodedFrame>>> mFragArray; - - // Codec specific data frame, it will be generated by encoder and send to - // ISOMediaWriter through WriteEncodedTrack(). The data will be vary depends - // on codec type. - RefPtr<EncodedFrame> mCSDFrame; - - // END_OF_STREAM from ContainerWriter - bool mEOS; -}; - -/** - * ISOControl will be carried to each box when box is created. It is the main - * bridge for box to output stream to ContainerWriter and retrieve information. - * ISOControl acts 3 different roles: - * 1. Holds the pointer of audio metadata, video metadata, fragment and - * pass them to boxes. - * 2. Provide the functions to generate the base structure of MP4; they are - * GenerateFtyp, GenerateMoov, GenerateMoof, and GenerateMfra. - * 3. The actually writer used by MuxOperation::Write() in each box. It provides - * writing methods for different kind of data; they are Write, WriteArray, - * WriteBits...etc. - */ -class ISOControl { - -friend class Box; - -public: - ISOControl(uint32_t aMuxingType); - ~ISOControl(); - - nsresult GenerateFtyp(); - nsresult GenerateMoov(); - nsresult GenerateMoof(uint32_t aTrackType); - - // Swap elementary stream pointer to output buffers. - uint32_t WriteAVData(nsTArray<uint8_t>& aArray); - - uint32_t Write(uint8_t* aBuf, uint32_t aSize); - - uint32_t Write(uint8_t aData); - - template <typename T> - uint32_t Write(T aData) { - MOZ_ASSERT(!mBitCount); - - aData = NativeEndian::swapToNetworkOrder(aData); - Write((uint8_t*)&aData, sizeof(T)); - return sizeof(T); - } - - template <typename T> - uint32_t WriteArray(const T &aArray, uint32_t aSize) { - MOZ_ASSERT(!mBitCount); - - uint32_t size = 0; - for (uint32_t i = 0; i < aSize; i++) { - size += Write(aArray[i]); - } - return size; - } - - uint32_t WriteFourCC(const char* aType); - - // Bit writing. Note: it needs to be byte-boundary before using - // others non-bit writing function. - uint32_t WriteBits(uint64_t aBits, size_t aNumBits); - - // This is called by GetContainerData and swap all the buffers to aOutputBuffers. - nsresult GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs); - - // Presentation time in seconds since midnight, Jan. 1, 1904, in UTC time. - uint32_t GetTime(); - - // current fragment number - uint32_t GetCurFragmentNumber() { return mFragNum; } - - nsresult SetFragment(FragmentBuffer* aFragment); - FragmentBuffer* GetFragment(uint32_t aType); - - uint32_t GetMuxingType() { return mMuxingType; } - - nsresult SetMetadata(TrackMetadataBase* aTrackMeta); - nsresult GetAudioMetadata(RefPtr<AudioTrackMetadata>& aAudMeta); - nsresult GetVideoMetadata(RefPtr<VideoTrackMetadata>& aVidMeta); - - // Track ID is the Metadata index in mMetaArray. It allows only 1 audio - // track and 1 video track in this muxer. In this muxer, it is prohibt to have - // mutiple audio track or video track in the same file. - uint32_t GetTrackID(TrackMetadataBase::MetadataKind aKind); - uint32_t GetNextTrackID(); - - bool HasAudioTrack(); - bool HasVideoTrack(); - -private: - uint32_t GetBufPos(); - nsresult FlushBuf(); - - // One of value in TYPE_XXX, defined in ISOMediaWriter. - uint32_t mMuxingType; - - // Audio and video fragments are owned by ISOMediaWriter. - // They don't need to worry about pointer going stale because ISOMediaWriter's - // lifetime is longer than ISOControl. - FragmentBuffer* mAudioFragmentBuffer; - FragmentBuffer* mVideoFragmentBuffer; - - // Generated fragment number - uint32_t mFragNum; - - // The (index + 1) will be the track ID. - nsTArray<RefPtr<TrackMetadataBase>> mMetaArray; - - // Array of output buffers. - // To save memory usage, audio/video sample will be swapped into a new element - // of this array. - // - // For example, - // mOutBuffers[0] --> boxes (allocated by muxer) - // mOutBuffers[1] --> video raw data (allocated by encoder) - // mOutBuffers[2] --> video raw data (allocated by encoder) - // mOutBuffers[3] --> video raw data (allocated by encoder) - // mOutBuffers[4] --> boxes (allocated by muxer) - // mOutBuffers[5] --> audio raw data (allocated by encoder) - // ...etc. - // - nsTArray<nsTArray<uint8_t>> mOutBuffers; - - // Accumulate output size from Write(). - uint64_t mOutputSize; - - // Bit writing operation. Note: the mBitCount should be 0 before any - // byte-boundary writing method be called (Write(uint32_t), Write(uint16_t)...etc); - // otherwise, there will be assertion on these functions. - uint8_t mBitCount; - uint8_t mBit; -}; - -} -#endif diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp deleted file mode 100644 index 32a0c577b..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp +++ /dev/null @@ -1,1550 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 <climits> -#include "TrackMetadataBase.h" -#include "ISOMediaBoxes.h" -#include "ISOControl.h" -#include "ISOMediaWriter.h" -#include "EncodedFrameContainer.h" -#include "ISOTrackMetadata.h" -#include "MP4ESDS.h" -#include "AMRBox.h" -#include "AVCBox.h" -#include "EVRCBox.h" -#include "VideoUtils.h" - -namespace mozilla { - -// 14496-12 6.2.2 'Data Types and fields' -const uint32_t iso_matrix[] = { 0x00010000, 0, 0, - 0, 0x00010000, 0, - 0, 0, 0x40000000 }; - -uint32_t -set_sample_flags(bool aSync) -{ - std::bitset<32> flags; - flags.set(16, !aSync); - return flags.to_ulong(); -} - -Box::BoxSizeChecker::BoxSizeChecker(ISOControl* aControl, uint32_t aSize) -{ - mControl = aControl; - ori_size = mControl->GetBufPos(); - box_size = aSize; - MOZ_COUNT_CTOR(BoxSizeChecker); -} - -Box::BoxSizeChecker::~BoxSizeChecker() -{ - uint32_t cur_size = mControl->GetBufPos(); - if ((cur_size - ori_size) != box_size) { - MOZ_ASSERT(false); - } - - MOZ_COUNT_DTOR(BoxSizeChecker); -} - -nsresult -MediaDataBox::Generate(uint32_t* aBoxSize) -{ - mFirstSampleOffset = size; - mAllSampleSize = 0; - - if (mTrackType & Audio_Track) { - FragmentBuffer* frag = mControl->GetFragment(Audio_Track); - mAllSampleSize += frag->GetFirstFragmentSampleSize(); - } - if (mTrackType & Video_Track) { - FragmentBuffer* frag = mControl->GetFragment(Video_Track); - mAllSampleSize += frag->GetFirstFragmentSampleSize(); - } - - size += mAllSampleSize; - *aBoxSize = size; - return NS_OK; -} - -nsresult -MediaDataBox::Write() -{ - nsresult rv; - BoxSizeChecker checker(mControl, size); - Box::Write(); - nsTArray<uint32_t> types; - types.AppendElement(Audio_Track); - types.AppendElement(Video_Track); - - for (uint32_t l = 0; l < types.Length(); l++) { - if (mTrackType & types[l]) { - FragmentBuffer* frag = mControl->GetFragment(types[l]); - nsTArray<RefPtr<EncodedFrame>> frames; - - // Here is the last time we get fragment frames, flush it! - rv = frag->GetFirstFragment(frames, true); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t len = frames.Length(); - for (uint32_t i = 0; i < len; i++) { - nsTArray<uint8_t> frame_buffer; - frames.ElementAt(i)->SwapOutFrameData(frame_buffer); - mControl->WriteAVData(frame_buffer); - } - } - } - - return NS_OK; -} - -MediaDataBox::MediaDataBox(uint32_t aTrackType, ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("mdat"), aControl) - , mAllSampleSize(0) - , mFirstSampleOffset(0) - , mTrackType(aTrackType) -{ - MOZ_COUNT_CTOR(MediaDataBox); -} - -MediaDataBox::~MediaDataBox() -{ - MOZ_COUNT_DTOR(MediaDataBox); -} - -uint32_t -TrackRunBox::fillSampleTable() -{ - uint32_t table_size = 0; - nsresult rv; - nsTArray<RefPtr<EncodedFrame>> frames; - FragmentBuffer* frag = mControl->GetFragment(mTrackType); - - rv = frag->GetFirstFragment(frames); - if (NS_FAILED(rv)) { - return 0; - } - uint32_t len = frames.Length(); - sample_info_table = MakeUnique<tbl[]>(len); - // Create sample table according to 14496-12 8.8.8.2. - for (uint32_t i = 0; i < len; i++) { - // Sample size. - sample_info_table[i].sample_size = 0; - if (flags.to_ulong() & flags_sample_size_present) { - sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length(); - mAllSampleSize += sample_info_table[i].sample_size; - table_size += sizeof(uint32_t); - } - - // Sample flags. - sample_info_table[i].sample_flags = 0; - if (flags.to_ulong() & flags_sample_flags_present) { - sample_info_table[i].sample_flags = - set_sample_flags( - (frames.ElementAt(i)->GetFrameType() == EncodedFrame::AVC_I_FRAME)); - table_size += sizeof(uint32_t); - } - - // Sample duration. - sample_info_table[i].sample_duration = 0; - if (flags.to_ulong() & flags_sample_duration_present) { - // Calculate each frame's duration, it is decided by "current frame - // timestamp - last frame timestamp". - uint64_t frame_time = 0; - if (i == 0) { - frame_time = frames.ElementAt(i)->GetTimeStamp() - - frag->GetLastFragmentLastFrameTime(); - } else { - frame_time = frames.ElementAt(i)->GetTimeStamp() - - frames.ElementAt(i - 1)->GetTimeStamp(); - // Keep the last frame time of current fagment, it will be used to calculate - // the first frame duration of next fragment. - if ((len - 1) == i) { - frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp()); - } - } - - // In TrackRunBox, there should be exactly one type, either audio or video. - MOZ_ASSERT((mTrackType & Video_Track) ^ (mTrackType & Audio_Track)); - sample_info_table[i].sample_duration = (mTrackType & Video_Track ? - frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S : - frame_time * mAudioMeta->GetAudioSampleRate() / USECS_PER_S); - - table_size += sizeof(uint32_t); - } - - sample_info_table[i].sample_composition_time_offset = 0; - } - return table_size; -} - -nsresult -TrackRunBox::Generate(uint32_t* aBoxSize) -{ - FragmentBuffer* frag = mControl->GetFragment(mTrackType); - sample_count = frag->GetFirstFragmentSampleNumber(); - size += sizeof(sample_count); - - // data_offset needs to be updated if there is other - // TrackRunBox before this one. - if (flags.to_ulong() & flags_data_offset_present) { - data_offset = 0; - size += sizeof(data_offset); - } - size += fillSampleTable(); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackRunBox::SetDataOffset(uint32_t aOffset) -{ - data_offset = aOffset; - return NS_OK; -} - -nsresult -TrackRunBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sample_count); - if (flags.to_ulong() & flags_data_offset_present) { - mControl->Write(data_offset); - } - for (uint32_t i = 0; i < sample_count; i++) { - if (flags.to_ulong() & flags_sample_duration_present) { - mControl->Write(sample_info_table[i].sample_duration); - } - if (flags.to_ulong() & flags_sample_size_present) { - mControl->Write(sample_info_table[i].sample_size); - } - if (flags.to_ulong() & flags_sample_flags_present) { - mControl->Write(sample_info_table[i].sample_flags); - } - } - - return NS_OK; -} - -TrackRunBox::TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("trun"), 0, aFlags, aControl) - , sample_count(0) - , data_offset(0) - , first_sample_flags(0) - , mAllSampleSize(0) - , mTrackType(aType) -{ - MOZ_COUNT_CTOR(TrackRunBox); -} - -TrackRunBox::~TrackRunBox() -{ - MOZ_COUNT_DTOR(TrackRunBox); -} - -nsresult -TrackFragmentHeaderBox::UpdateBaseDataOffset(uint64_t aOffset) -{ - base_data_offset = aOffset; - return NS_OK; -} - -nsresult -TrackFragmentHeaderBox::Generate(uint32_t* aBoxSize) -{ - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - size += sizeof(track_ID); - - if (flags.to_ulong() & base_data_offset_present) { - // base_data_offset needs to add size of 'trun', 'tfhd' and - // header of 'mdat' later. - base_data_offset = 0; - size += sizeof(base_data_offset); - } - if (flags.to_ulong() & default_sample_duration_present) { - if (mTrackType == Video_Track) { - if (!mVideoMeta->GetVideoFrameRate()) { - // 0 means frame rate is variant, so it is wrong to write - // default_sample_duration. - MOZ_ASSERT(0); - default_sample_duration = 0; - } else { - default_sample_duration = mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate(); - } - } else if (mTrackType == Audio_Track) { - default_sample_duration = mAudioMeta->GetAudioFrameDuration(); - } else { - MOZ_ASSERT(0); - return NS_ERROR_FAILURE; - } - size += sizeof(default_sample_duration); - } - *aBoxSize = size; - return NS_OK; -} - -nsresult -TrackFragmentHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(track_ID); - if (flags.to_ulong() & base_data_offset_present) { - mControl->Write(base_data_offset); - } - if (flags.to_ulong() & default_sample_duration_present) { - mControl->Write(default_sample_duration); - } - return NS_OK; -} - -TrackFragmentHeaderBox::TrackFragmentHeaderBox(uint32_t aType, - uint32_t aFlags, - ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("tfhd"), 0, aFlags, aControl) - , track_ID(0) - , base_data_offset(0) - , default_sample_duration(0) -{ - mTrackType = aType; - MOZ_COUNT_CTOR(TrackFragmentHeaderBox); -} - -TrackFragmentHeaderBox::~TrackFragmentHeaderBox() -{ - MOZ_COUNT_DTOR(TrackFragmentHeaderBox); -} - -TrackFragmentBox::TrackFragmentBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("traf"), aControl) - , mTrackType(aType) -{ - // Flags in TrackFragmentHeaderBox. - uint32_t tf_flags = base_data_offset_present; - - // Ideally, audio encoder generates audio frame in const rate. However, some - // audio encoders don't do it so the audio frame duration needs to be checked - // here. - if ((mTrackType & Audio_Track) && mAudioMeta->GetAudioFrameDuration()) { - tf_flags |= default_sample_duration_present; - } - - boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl)); - - // Always adds flags_data_offset_present in each TrackRunBox, Android - // parser requires this flag to calculate the correct bitstream offset. - uint32_t tr_flags = flags_sample_size_present | flags_data_offset_present; - - // Flags in TrackRunBox. - // If there is no default sample duration exists, each frame duration needs to - // be recored in the TrackRunBox. - tr_flags |= (tf_flags & default_sample_duration_present ? 0 : flags_sample_duration_present); - - // For video, add sample_flags to record I frame. - tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0); - - boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl)); - MOZ_COUNT_CTOR(TrackFragmentBox); -} - -TrackFragmentBox::~TrackFragmentBox() -{ - MOZ_COUNT_DTOR(TrackFragmentBox); -} - -nsresult -MovieFragmentHeaderBox::Generate(uint32_t* aBoxSize) -{ - sequence_number = mControl->GetCurFragmentNumber(); - size += sizeof(sequence_number); - *aBoxSize = size; - return NS_OK; -} - -nsresult -MovieFragmentHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sequence_number); - return NS_OK; -} - -MovieFragmentHeaderBox::MovieFragmentHeaderBox(uint32_t aTrackType, - ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mfhd"), 0, 0, aControl) - , sequence_number(0) - , mTrackType(aTrackType) -{ - MOZ_COUNT_CTOR(MovieFragmentHeaderBox); -} - -MovieFragmentHeaderBox::~MovieFragmentHeaderBox() -{ - MOZ_COUNT_DTOR(MovieFragmentHeaderBox); -} - -MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("moof"), aControl) - , mTrackType(aType) -{ - boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl)); - - if (mTrackType & Audio_Track) { - boxes.AppendElement( - new TrackFragmentBox(Audio_Track, aControl)); - } - if (mTrackType & Video_Track) { - boxes.AppendElement( - new TrackFragmentBox(Video_Track, aControl)); - } - MOZ_COUNT_CTOR(MovieFragmentBox); -} - -MovieFragmentBox::~MovieFragmentBox() -{ - MOZ_COUNT_DTOR(MovieFragmentBox); -} - -nsresult -MovieFragmentBox::Generate(uint32_t* aBoxSize) -{ - nsresult rv = DefaultContainerImpl::Generate(aBoxSize); - NS_ENSURE_SUCCESS(rv, rv); - - // Correct data_offset if there are both audio and video track in - // this fragment. This offset means the offset in the MediaDataBox. - if (mTrackType & (Audio_Track | Video_Track)) { - nsTArray<RefPtr<MuxerOperation>> truns; - rv = Find(NS_LITERAL_CSTRING("trun"), truns); - NS_ENSURE_SUCCESS(rv, rv); - uint32_t len = truns.Length(); - uint32_t data_offset = 0; - for (uint32_t i = 0; i < len; i++) { - TrackRunBox* trun = (TrackRunBox*) truns.ElementAt(i).get(); - rv = trun->SetDataOffset(data_offset); - NS_ENSURE_SUCCESS(rv, rv); - data_offset += trun->GetAllSampleSize(); - } - } - - return NS_OK; -} - -nsresult -TrackExtendsBox::Generate(uint32_t* aBoxSize) -{ - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - - if (mTrackType == Audio_Track) { - default_sample_description_index = 1; - default_sample_duration = mAudioMeta->GetAudioFrameDuration(); - default_sample_size = mAudioMeta->GetAudioFrameSize(); - default_sample_flags = set_sample_flags(1); - } else if (mTrackType == Video_Track) { - default_sample_description_index = 1; - // Video meta data has assigned framerate, it implies that this video's - // frame rate should be fixed. - if (mVideoMeta->GetVideoFrameRate()) { - default_sample_duration = - mVideoMeta->GetVideoClockRate() / mVideoMeta->GetVideoFrameRate(); - } - default_sample_size = 0; - default_sample_flags = set_sample_flags(0); - } else { - MOZ_ASSERT(0); - return NS_ERROR_FAILURE; - } - - size += sizeof(track_ID) + - sizeof(default_sample_description_index) + - sizeof(default_sample_duration) + - sizeof(default_sample_size) + - sizeof(default_sample_flags); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackExtendsBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(track_ID); - mControl->Write(default_sample_description_index); - mControl->Write(default_sample_duration); - mControl->Write(default_sample_size); - mControl->Write(default_sample_flags); - - return NS_OK; -} - -TrackExtendsBox::TrackExtendsBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("trex"), 0, 0, aControl) - , track_ID(0) - , default_sample_description_index(0) - , default_sample_duration(0) - , default_sample_size(0) - , default_sample_flags(0) - , mTrackType(aType) -{ - MOZ_COUNT_CTOR(TrackExtendsBox); -} - -TrackExtendsBox::~TrackExtendsBox() -{ - MOZ_COUNT_DTOR(TrackExtendsBox); -} - -MovieExtendsBox::MovieExtendsBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("mvex"), aControl) -{ - if (mAudioMeta) { - boxes.AppendElement(new TrackExtendsBox(Audio_Track, aControl)); - } - if (mVideoMeta) { - boxes.AppendElement(new TrackExtendsBox(Video_Track, aControl)); - } - MOZ_COUNT_CTOR(MovieExtendsBox); -} - -MovieExtendsBox::~MovieExtendsBox() -{ - MOZ_COUNT_DTOR(MovieExtendsBox); -} - -nsresult -ChunkOffsetBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4. - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -ChunkOffsetBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -ChunkOffsetBox::ChunkOffsetBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stco"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(ChunkOffsetBox); -} - -ChunkOffsetBox::~ChunkOffsetBox() -{ - MOZ_COUNT_DTOR(ChunkOffsetBox); -} - -nsresult -SampleToChunkBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4 - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -SampleToChunkBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -SampleToChunkBox::SampleToChunkBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsc"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(SampleToChunkBox); -} - -SampleToChunkBox::~SampleToChunkBox() -{ - MOZ_COUNT_DTOR(SampleToChunkBox); -} - -nsresult -TimeToSampleBox::Generate(uint32_t* aBoxSize) -{ - // We don't need time to sample table in fragmented mp4. - entry_count = 0; - size += sizeof(entry_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -TimeToSampleBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - return NS_OK; -} - -TimeToSampleBox::TimeToSampleBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stts"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(TimeToSampleBox); -} - -TimeToSampleBox::~TimeToSampleBox() -{ - MOZ_COUNT_DTOR(TimeToSampleBox); -} - -nsresult -SampleDescriptionBox::Generate(uint32_t* aBoxSize) -{ - entry_count = 1; - size += sizeof(entry_count); - - nsresult rv; - uint32_t box_size; - rv = sample_entry_box->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - *aBoxSize = size; - - return NS_OK; -} - -nsresult -SampleDescriptionBox::Write() -{ - WRITE_FULLBOX(mControl, size) - nsresult rv; - mControl->Write(entry_count); - rv = sample_entry_box->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -SampleDescriptionBox::SampleDescriptionBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsd"), 0, 0, aControl) - , entry_count(0) -{ - mTrackType = aType; - - switch (mTrackType) { - case Audio_Track: - { - CreateAudioSampleEntry(sample_entry_box); - } - break; - case Video_Track: - { - CreateVideoSampleEntry(sample_entry_box); - } - break; - } - MOZ_ASSERT(sample_entry_box); - MOZ_COUNT_CTOR(SampleDescriptionBox); -} - -nsresult -SampleDescriptionBox::CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry) -{ - if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AMR) { - aSampleEntry = new AMRSampleEntry(mControl); - } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_AAC) { - aSampleEntry = new MP4AudioSampleEntry(mControl); - } else if (mAudioMeta->GetKind() == TrackMetadataBase::METADATA_EVRC) { - aSampleEntry = new EVRCSampleEntry(mControl); - } else { - MOZ_ASSERT(0); - } - return NS_OK; -} - -nsresult -SampleDescriptionBox::CreateVideoSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry) -{ - if (mVideoMeta->GetKind() == TrackMetadataBase::METADATA_AVC) { - aSampleEntry = new AVCSampleEntry(mControl); - } else { - MOZ_ASSERT(0); - } - return NS_OK; -} - -SampleDescriptionBox::~SampleDescriptionBox() -{ - MOZ_COUNT_DTOR(SampleDescriptionBox); -} - -nsresult -SampleSizeBox::Generate(uint32_t* aBoxSize) -{ - size += sizeof(sample_size) + - sizeof(sample_count); - *aBoxSize = size; - return NS_OK; -} - -nsresult -SampleSizeBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(sample_size); - mControl->Write(sample_count); - return NS_OK; -} - -SampleSizeBox::SampleSizeBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("stsz"), 0, 0, aControl) - , sample_size(0) - , sample_count(0) -{ - MOZ_COUNT_CTOR(SampleSizeBox); -} - -SampleSizeBox::~SampleSizeBox() -{ - MOZ_COUNT_DTOR(SampleSizeBox); -} - -SampleTableBox::SampleTableBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("stbl"), aControl) -{ - boxes.AppendElement(new SampleDescriptionBox(aType, aControl)); - boxes.AppendElement(new TimeToSampleBox(aType, aControl)); - boxes.AppendElement(new SampleToChunkBox(aType, aControl)); - boxes.AppendElement(new SampleSizeBox(aControl)); - boxes.AppendElement(new ChunkOffsetBox(aType, aControl)); - MOZ_COUNT_CTOR(SampleTableBox); -} - -SampleTableBox::~SampleTableBox() -{ - MOZ_COUNT_DTOR(SampleTableBox); -} - -nsresult -DataEntryUrlBox::Generate(uint32_t* aBoxSize) -{ - // location is null here, do nothing - size += location.Length(); - *aBoxSize = size; - - return NS_OK; -} - -nsresult -DataEntryUrlBox::Write() -{ - WRITE_FULLBOX(mControl, size) - return NS_OK; -} - -DataEntryUrlBox::DataEntryUrlBox() - : FullBox(NS_LITERAL_CSTRING("url "), 0, 0, (ISOControl*) nullptr) -{ - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::DataEntryUrlBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("url "), 0, flags_media_at_the_same_file, aControl) -{ - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::DataEntryUrlBox(const DataEntryUrlBox& aBox) - : FullBox(aBox.boxType, aBox.version, aBox.flags.to_ulong(), aBox.mControl) -{ - location = aBox.location; - MOZ_COUNT_CTOR(DataEntryUrlBox); -} - -DataEntryUrlBox::~DataEntryUrlBox() -{ - MOZ_COUNT_DTOR(DataEntryUrlBox); -} - -nsresult DataReferenceBox::Generate(uint32_t* aBoxSize) -{ - entry_count = 1; // only allow on entry here - size += sizeof(uint32_t); - - for (uint32_t i = 0; i < entry_count; i++) { - uint32_t box_size = 0; - DataEntryUrlBox* url = new DataEntryUrlBox(mControl); - url->Generate(&box_size); - size += box_size; - urls.AppendElement(url); - } - - *aBoxSize = size; - - return NS_OK; -} - -nsresult DataReferenceBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(entry_count); - - for (uint32_t i = 0; i < entry_count; i++) { - urls[i]->Write(); - } - - return NS_OK; -} - -DataReferenceBox::DataReferenceBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("dref"), 0, 0, aControl) - , entry_count(0) -{ - MOZ_COUNT_CTOR(DataReferenceBox); -} - -DataReferenceBox::~DataReferenceBox() -{ - MOZ_COUNT_DTOR(DataReferenceBox); -} - -DataInformationBox::DataInformationBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("dinf"), aControl) -{ - boxes.AppendElement(new DataReferenceBox(aControl)); - MOZ_COUNT_CTOR(DataInformationBox); -} - -DataInformationBox::~DataInformationBox() -{ - MOZ_COUNT_DTOR(DataInformationBox); -} - -nsresult -VideoMediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - size += sizeof(graphicsmode) + - sizeof(opcolor); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -VideoMediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(graphicsmode); - mControl->WriteArray(opcolor, 3); - return NS_OK; -} - -VideoMediaHeaderBox::VideoMediaHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("vmhd"), 0, 1, aControl) - , graphicsmode(0) -{ - memset(opcolor, 0 , sizeof(opcolor)); - MOZ_COUNT_CTOR(VideoMediaHeaderBox); -} - -VideoMediaHeaderBox::~VideoMediaHeaderBox() -{ - MOZ_COUNT_DTOR(VideoMediaHeaderBox); -} - -nsresult -SoundMediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - balance = 0; - reserved = 0; - size += sizeof(balance) + - sizeof(reserved); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -SoundMediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(balance); - mControl->Write(reserved); - - return NS_OK; -} - -SoundMediaHeaderBox::SoundMediaHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("smhd"), 0, 0, aControl) -{ - MOZ_COUNT_CTOR(SoundMediaHeaderBox); -} - -SoundMediaHeaderBox::~SoundMediaHeaderBox() -{ - MOZ_COUNT_DTOR(SoundMediaHeaderBox); -} - -MediaInformationBox::MediaInformationBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("minf"), aControl) -{ - mTrackType = aType; - - if (mTrackType == Audio_Track) { - boxes.AppendElement(new SoundMediaHeaderBox(aControl)); - } else if (mTrackType == Video_Track) { - boxes.AppendElement(new VideoMediaHeaderBox(aControl)); - } else { - MOZ_ASSERT(0); - } - - boxes.AppendElement(new DataInformationBox(aControl)); - boxes.AppendElement(new SampleTableBox(aType, aControl)); - MOZ_COUNT_CTOR(MediaInformationBox); -} - -MediaInformationBox::~MediaInformationBox() -{ - MOZ_COUNT_DTOR(MediaInformationBox); -} - -nsresult -HandlerBox::Generate(uint32_t* aBoxSize) -{ - pre_defined = 0; - if (mTrackType == Audio_Track) { - handler_type = FOURCC('s', 'o', 'u', 'n'); - } else if (mTrackType == Video_Track) { - handler_type = FOURCC('v', 'i', 'd', 'e'); - } - - size += sizeof(pre_defined) + - sizeof(handler_type) + - sizeof(reserved); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -HandlerBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(pre_defined); - mControl->Write(handler_type); - mControl->WriteArray(reserved, 3); - - return NS_OK; -} - -HandlerBox::HandlerBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("hdlr"), 0, 0, aControl) - , pre_defined(0) - , handler_type(0) -{ - mTrackType = aType; - memset(reserved, 0 , sizeof(reserved)); - MOZ_COUNT_CTOR(HandlerBox); -} - -HandlerBox::~HandlerBox() -{ - MOZ_COUNT_DTOR(HandlerBox); -} - -MediaHeaderBox::MediaHeaderBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mdhd"), 0, 0, aControl) - , creation_time(0) - , modification_time(0) - , timescale(0) - , duration(0) - , pad(0) - , lang1(0) - , lang2(0) - , lang3(0) - , pre_defined(0) -{ - mTrackType = aType; - MOZ_COUNT_CTOR(MediaHeaderBox); -} - -MediaHeaderBox::~MediaHeaderBox() -{ - MOZ_COUNT_DTOR(MediaHeaderBox); -} - -uint32_t -MediaHeaderBox::GetTimeScale() -{ - if (mTrackType == Audio_Track) { - return mAudioMeta->GetAudioSampleRate(); - } - - return mVideoMeta->GetVideoClockRate(); -} - -nsresult -MediaHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - timescale = GetTimeScale(); - duration = 0; // fragmented mp4 - - pad = 0; - lang1 = 'u' - 0x60; // "und" underdetermined language - lang2 = 'n' - 0x60; - lang3 = 'd' - 0x60; - size += (pad.size() + lang1.size() + lang2.size() + lang3.size()) / CHAR_BIT; - - pre_defined = 0; - size += sizeof(creation_time) + - sizeof(modification_time) + - sizeof(timescale) + - sizeof(duration) + - sizeof(pre_defined); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -MediaHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(timescale); - mControl->Write(duration); - mControl->WriteBits(pad.to_ulong(), pad.size()); - mControl->WriteBits(lang1.to_ulong(), lang1.size()); - mControl->WriteBits(lang2.to_ulong(), lang2.size()); - mControl->WriteBits(lang3.to_ulong(), lang3.size()); - mControl->Write(pre_defined); - - return NS_OK; -} - -MovieBox::MovieBox(ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("moov"), aControl) -{ - boxes.AppendElement(new MovieHeaderBox(aControl)); - if (aControl->HasAudioTrack()) { - boxes.AppendElement(new TrackBox(Audio_Track, aControl)); - } - if (aControl->HasVideoTrack()) { - boxes.AppendElement(new TrackBox(Video_Track, aControl)); - } - boxes.AppendElement(new MovieExtendsBox(aControl)); - MOZ_COUNT_CTOR(MovieBox); -} - -MovieBox::~MovieBox() -{ - MOZ_COUNT_DTOR(MovieBox); -} - -nsresult -MovieHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - timescale = GetTimeScale(); - duration = 0; // The duration is always 0 in fragmented mp4. - next_track_ID = mControl->GetNextTrackID(); - - size += sizeof(next_track_ID) + - sizeof(creation_time) + - sizeof(modification_time) + - sizeof(timescale) + - sizeof(duration) + - sizeof(rate) + - sizeof(volume) + - sizeof(reserved16) + - sizeof(reserved32) + - sizeof(matrix) + - sizeof(pre_defined); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -MovieHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(timescale); - mControl->Write(duration); - mControl->Write(rate); - mControl->Write(volume); - mControl->Write(reserved16); - mControl->WriteArray(reserved32, 2); - mControl->WriteArray(matrix, 9); - mControl->WriteArray(pre_defined, 6); - mControl->Write(next_track_ID); - - return NS_OK; -} - -uint32_t -MovieHeaderBox::GetTimeScale() -{ - // Only audio track in container. - if (mAudioMeta && !mVideoMeta) { - return mAudioMeta->GetAudioSampleRate(); - } - - // return video rate - return mVideoMeta->GetVideoClockRate(); -} - -MovieHeaderBox::~MovieHeaderBox() -{ - MOZ_COUNT_DTOR(MovieHeaderBox); -} - -MovieHeaderBox::MovieHeaderBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("mvhd"), 0, 0, aControl) - , creation_time(0) - , modification_time(0) - , timescale(90000) - , duration(0) - , rate(0x00010000) - , volume(0x0100) - , reserved16(0) - , next_track_ID(1) -{ - memcpy(matrix, iso_matrix, sizeof(matrix)); - memset(reserved32, 0, sizeof(reserved32)); - memset(pre_defined, 0, sizeof(pre_defined)); - MOZ_COUNT_CTOR(MovieHeaderBox); -} - -TrackHeaderBox::TrackHeaderBox(uint32_t aType, ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("tkhd"), 0, - flags_track_enabled | flags_track_in_movie | flags_track_in_preview, - aControl) - , creation_time(0) - , modification_time(0) - , track_ID(0) - , reserved(0) - , duration(0) - , layer(0) - , alternate_group(0) - , volume(0) - , reserved3(0) - , width(0) - , height(0) -{ - mTrackType = aType; - memcpy(matrix, iso_matrix, sizeof(matrix)); - memset(reserved2, 0, sizeof(reserved2)); - MOZ_COUNT_CTOR(TrackHeaderBox); -} - -TrackHeaderBox::~TrackHeaderBox() -{ - MOZ_COUNT_DTOR(TrackHeaderBox); -} - -nsresult -TrackHeaderBox::Generate(uint32_t* aBoxSize) -{ - creation_time = mControl->GetTime(); - modification_time = mControl->GetTime(); - track_ID = (mTrackType == Audio_Track ? - mControl->GetTrackID(mAudioMeta->GetKind()) : - mControl->GetTrackID(mVideoMeta->GetKind())); - // fragmented mp4 - duration = 0; - - // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2 - volume = (mTrackType == Audio_Track ? 0x0100 : 0); - - if (mTrackType == Video_Track) { - width = mVideoMeta->GetVideoDisplayWidth() << 16; - height = mVideoMeta->GetVideoDisplayHeight() << 16; - // Check display size, using the pixel size if any of them is invalid. - if (!width || !height) { - width = mVideoMeta->GetVideoWidth() << 16; - height = mVideoMeta->GetVideoHeight() << 16; - } - } - - size += sizeof(creation_time) + - sizeof(modification_time) + - sizeof(track_ID) + - sizeof(reserved) + - sizeof(duration) + - sizeof(reserved2) + - sizeof(layer) + - sizeof(alternate_group) + - sizeof(volume) + - sizeof(reserved3) + - sizeof(matrix) + - sizeof(width) + - sizeof(height); - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -TrackHeaderBox::Write() -{ - WRITE_FULLBOX(mControl, size) - mControl->Write(creation_time); - mControl->Write(modification_time); - mControl->Write(track_ID); - mControl->Write(reserved); - mControl->Write(duration); - mControl->WriteArray(reserved2, 2); - mControl->Write(layer); - mControl->Write(alternate_group); - mControl->Write(volume); - mControl->Write(reserved3); - mControl->WriteArray(matrix, 9); - mControl->Write(width); - mControl->Write(height); - - return NS_OK; -} - -nsresult -FileTypeBox::Generate(uint32_t* aBoxSize) -{ - minor_version = 0; - - if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_MP4) { - if (!mControl->HasVideoTrack() && mControl->HasAudioTrack()) { - major_brand = "M4A "; - } else { - major_brand = "MP42"; - } - compatible_brands.AppendElement("mp42"); - compatible_brands.AppendElement("isom"); - } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3GP) { - major_brand = "3gp9"; - // According to 3GPP TS 26.244 V12.2.0, section 5.3.4, it's recommended to - // list all compatible brands here. 3GP spec supports fragment from '3gp6'. - compatible_brands.AppendElement("3gp9"); - compatible_brands.AppendElement("3gp8"); - compatible_brands.AppendElement("3gp7"); - compatible_brands.AppendElement("3gp6"); - compatible_brands.AppendElement("isom"); - } else if (mControl->GetMuxingType() == ISOMediaWriter::TYPE_FRAG_3G2) { - major_brand = "3g2a"; - // 3GPP2 Release 0 and A and 3GPP Release 6 allow movie fragmentation - compatible_brands.AppendElement("3gp9"); - compatible_brands.AppendElement("3gp8"); - compatible_brands.AppendElement("3gp7"); - compatible_brands.AppendElement("3gp6"); - compatible_brands.AppendElement("isom"); - compatible_brands.AppendElement("3g2c"); - compatible_brands.AppendElement("3g2b"); - compatible_brands.AppendElement("3g2a"); - } else { - MOZ_ASSERT(0); - } - - size += major_brand.Length() + - sizeof(minor_version) + - compatible_brands.Length() * 4; - - *aBoxSize = size; - - return NS_OK; -} - -nsresult -FileTypeBox::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - mControl->WriteFourCC(major_brand.get()); - mControl->Write(minor_version); - uint32_t len = compatible_brands.Length(); - for (uint32_t i = 0; i < len; i++) { - mControl->WriteFourCC(compatible_brands[i].get()); - } - - return NS_OK; -} - -FileTypeBox::FileTypeBox(ISOControl* aControl) - : Box(NS_LITERAL_CSTRING("ftyp"), aControl) - , minor_version(0) -{ - MOZ_COUNT_CTOR(FileTypeBox); -} - -FileTypeBox::~FileTypeBox() -{ - MOZ_COUNT_DTOR(FileTypeBox); -} - -MediaBox::MediaBox(uint32_t aType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("mdia"), aControl) -{ - mTrackType = aType; - boxes.AppendElement(new MediaHeaderBox(aType, aControl)); - boxes.AppendElement(new HandlerBox(aType, aControl)); - boxes.AppendElement(new MediaInformationBox(aType, aControl)); - MOZ_COUNT_CTOR(MediaBox); -} - -MediaBox::~MediaBox() -{ - MOZ_COUNT_DTOR(MediaBox); -} - -nsresult -DefaultContainerImpl::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - uint32_t box_size; - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - } - *aBoxSize = size; - return NS_OK; -} - -nsresult -DefaultContainerImpl::Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) -{ - nsresult rv = Box::Find(aType, aOperations); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Find(aType, aOperations); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - -nsresult -DefaultContainerImpl::Write() -{ - BoxSizeChecker checker(mControl, size); - Box::Write(); - - nsresult rv; - uint32_t len = boxes.Length(); - for (uint32_t i = 0; i < len; i++) { - rv = boxes.ElementAt(i)->Write(); - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; -} - -DefaultContainerImpl::DefaultContainerImpl(const nsACString& aType, - ISOControl* aControl) - : Box(aType, aControl) -{ -} - -nsresult -Box::Write() -{ - mControl->Write(size); - mControl->WriteFourCC(boxType.get()); - return NS_OK; -} - -nsresult -Box::Find(const nsACString& aType, nsTArray<RefPtr<MuxerOperation>>& aOperations) -{ - if (boxType == aType) { - aOperations.AppendElement(this); - } - return NS_OK; -} - -Box::Box(const nsACString& aType, ISOControl* aControl) - : size(8), mControl(aControl) -{ - MOZ_ASSERT(aType.Length() == 4); - boxType = aType; - aControl->GetAudioMetadata(mAudioMeta); - aControl->GetVideoMetadata(mVideoMeta); -} - -FullBox::FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags, - ISOControl* aControl) - : Box(aType, aControl) -{ - std::bitset<24> tmp_flags(aFlags); - version = aVersion; - flags = tmp_flags; - size += sizeof(version) + flags.size() / CHAR_BIT; -} - -nsresult -FullBox::Write() -{ - Box::Write(); - mControl->Write(version); - mControl->WriteBits(flags.to_ulong(), flags.size()); - return NS_OK; -} - -TrackBox::TrackBox(uint32_t aTrackType, ISOControl* aControl) - : DefaultContainerImpl(NS_LITERAL_CSTRING("trak"), aControl) -{ - boxes.AppendElement(new TrackHeaderBox(aTrackType, aControl)); - boxes.AppendElement(new MediaBox(aTrackType, aControl)); - MOZ_COUNT_CTOR(TrackBox); -} - -TrackBox::~TrackBox() -{ - MOZ_COUNT_DTOR(TrackBox); -} - -SampleEntryBox::SampleEntryBox(const nsACString& aFormat, ISOControl* aControl) - : Box(aFormat, aControl) - , data_reference_index(0) -{ - data_reference_index = 1; // There is only one data reference in each track. - size += sizeof(reserved) + - sizeof(data_reference_index); - memset(reserved, 0, sizeof(reserved)); -} - -nsresult -SampleEntryBox::Write() -{ - Box::Write(); - mControl->Write(reserved, sizeof(reserved)); - mControl->Write(data_reference_index); - return NS_OK; -} - -nsresult -AudioSampleEntry::Write() -{ - SampleEntryBox::Write(); - mControl->Write(sound_version); - mControl->Write(reserved2, sizeof(reserved2)); - mControl->Write(channels); - mControl->Write(sample_size); - mControl->Write(compressionId); - mControl->Write(packet_size); - mControl->Write(timeScale); - return NS_OK; -} - -AudioSampleEntry::AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl) - : SampleEntryBox(aFormat, aControl) - , sound_version(0) - , channels(2) - , sample_size(16) - , compressionId(0) - , packet_size(0) - , timeScale(0) -{ - memset(reserved2, 0 , sizeof(reserved2)); - channels = mAudioMeta->GetAudioChannels(); - timeScale = mAudioMeta->GetAudioSampleRate() << 16; - - size += sizeof(sound_version) + - sizeof(reserved2) + - sizeof(sample_size) + - sizeof(channels) + - sizeof(packet_size) + - sizeof(compressionId) + - sizeof(timeScale); - - MOZ_COUNT_CTOR(AudioSampleEntry); -} - -AudioSampleEntry::~AudioSampleEntry() -{ - MOZ_COUNT_DTOR(AudioSampleEntry); -} - -nsresult -VisualSampleEntry::Write() -{ - SampleEntryBox::Write(); - - mControl->Write(reserved, sizeof(reserved)); - mControl->Write(width); - mControl->Write(height); - mControl->Write(horizresolution); - mControl->Write(vertresolution); - mControl->Write(reserved2); - mControl->Write(frame_count); - mControl->Write(compressorName, sizeof(compressorName)); - mControl->Write(depth); - mControl->Write(pre_defined); - - return NS_OK; -} - -VisualSampleEntry::VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl) - : SampleEntryBox(aFormat, aControl) - , width(0) - , height(0) - , horizresolution(resolution_72_dpi) - , vertresolution(resolution_72_dpi) - , reserved2(0) - , frame_count(1) - , depth(video_depth) - , pre_defined(-1) -{ - memset(reserved, 0 , sizeof(reserved)); - memset(compressorName, 0 , sizeof(compressorName)); - - // both fields occupy 16 bits defined in 14496-2 6.2.3. - width = mVideoMeta->GetVideoWidth(); - height = mVideoMeta->GetVideoHeight(); - - size += sizeof(reserved) + - sizeof(width) + - sizeof(height) + - sizeof(horizresolution) + - sizeof(vertresolution) + - sizeof(reserved2) + - sizeof(frame_count) + - sizeof(compressorName) + - sizeof(depth) + - sizeof(pre_defined); - - MOZ_COUNT_CTOR(VisualSampleEntry); -} - -VisualSampleEntry::~VisualSampleEntry() -{ - MOZ_COUNT_DTOR(VisualSampleEntry); -} - -} diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h deleted file mode 100644 index a6dc1b046..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h +++ /dev/null @@ -1,781 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 ISOMediaBoxes_h_ -#define ISOMediaBoxes_h_ - -#include <bitset> -#include "nsString.h" -#include "nsTArray.h" -#include "nsAutoPtr.h" -#include "MuxerOperation.h" -#include "mozilla/UniquePtr.h" - -#define WRITE_FULLBOX(_compositor, _size) \ - BoxSizeChecker checker(_compositor, _size); \ - FullBox::Write(); - -#define FOURCC(a, b, c, d) ( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d) ) - -namespace mozilla { - -/** - * track type from spec 8.4.3.3 - */ -#define Audio_Track 0x01 -#define Video_Track 0x02 - -class AudioTrackMetadata; -class VideoTrackMetadata; -class ISOControl; - -/** - * This is the base class for all ISO media format boxes. - * It provides the fields of box type(four CC) and size. - * The data members in the beginning of a Box (or its descendants) - * are the 14496-12 defined member. Other members prefix with 'm' - * are private control data. - * - * This class is for inherited only, it shouldn't be instanced directly. - */ -class Box : public MuxerOperation { -protected: - // ISO BMFF members - uint32_t size; // 14496-12 4-2 'Object Structure'. Size of this box. - nsCString boxType; // four CC name, all table names are listed in - // 14496-12 table 1. - -public: - // MuxerOperation methods - nsresult Write() override; - nsresult Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) override; - - // This helper class will compare the written size in Write() and the size in - // Generate(). If their are not equal, it will assert. - class BoxSizeChecker { - public: - BoxSizeChecker(ISOControl* aControl, uint32_t aSize); - ~BoxSizeChecker(); - - uint32_t ori_size; - uint32_t box_size; - ISOControl* mControl; - }; - -protected: - Box() = delete; - Box(const nsACString& aType, ISOControl* aControl); - - ISOControl* mControl; - RefPtr<AudioTrackMetadata> mAudioMeta; - RefPtr<VideoTrackMetadata> mVideoMeta; -}; - -/** - * FullBox (and its descendants) is the box which contains the 'real' data - * members. It is the edge in the ISO box structure and it doesn't contain - * any box. - * - * This class is for inherited only, it shouldn't be instanced directly. - */ -class FullBox : public Box { -public: - // ISO BMFF members - uint8_t version; // 14496-12 4.2 'Object Structure' - std::bitset<24> flags; // - - // MuxerOperation methods - nsresult Write() override; - -protected: - // FullBox methods - FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags, - ISOControl* aControl); - FullBox() = delete; -}; - -/** - * The default implementation of the container box. - * Basically, the container box inherits this class and overrides the - * constructor only. - * - * According to 14496-12 3.1.1 'container box', a container box is - * 'box whose sole purpose is to contain and group a set of related boxes' - * - * This class is for inherited only, it shouldn't be instanced directly. - */ -class DefaultContainerImpl : public Box { -public: - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - nsresult Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) override; - -protected: - // DefaultContainerImpl methods - DefaultContainerImpl(const nsACString& aType, ISOControl* aControl); - DefaultContainerImpl() = delete; - - nsTArray<RefPtr<MuxerOperation>> boxes; -}; - -// 14496-12 4.3 'File Type Box' -// Box type: 'ftyp' -class FileTypeBox : public Box { -public: - // ISO BMFF members - nsCString major_brand; // four chars - uint32_t minor_version; - nsTArray<nsCString> compatible_brands; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // FileTypeBox methods - FileTypeBox(ISOControl* aControl); - ~FileTypeBox(); -}; - -// 14496-12 8.2.1 'Movie Box' -// Box type: 'moov' -// MovieBox contains MovieHeaderBox, TrackBox and MovieExtendsBox. -class MovieBox : public DefaultContainerImpl { -public: - MovieBox(ISOControl* aControl); - ~MovieBox(); -}; - -// 14496-12 8.2.2 'Movie Header Box' -// Box type: 'mvhd' -class MovieHeaderBox : public FullBox { -public: - // ISO BMFF members - uint32_t creation_time; - uint32_t modification_time; - uint32_t timescale; - uint32_t duration; - uint32_t rate; - uint16_t volume; - uint16_t reserved16; - uint32_t reserved32[2]; - uint32_t matrix[9]; - uint32_t pre_defined[6]; - uint32_t next_track_ID; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // MovieHeaderBox methods - MovieHeaderBox(ISOControl* aControl); - ~MovieHeaderBox(); - uint32_t GetTimeScale(); -}; - -// 14496-12 8.4.2 'Media Header Box' -// Box type: 'mdhd' -class MediaHeaderBox : public FullBox { -public: - // ISO BMFF members - uint32_t creation_time; - uint32_t modification_time; - uint32_t timescale; - uint32_t duration; - std::bitset<1> pad; - std::bitset<5> lang1; - std::bitset<5> lang2; - std::bitset<5> lang3; - uint16_t pre_defined; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // MediaHeaderBox methods - MediaHeaderBox(uint32_t aType, ISOControl* aControl); - ~MediaHeaderBox(); - uint32_t GetTimeScale(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.3.1 'Track Box' -// Box type: 'trak' -// TrackBox contains TrackHeaderBox and MediaBox. -class TrackBox : public DefaultContainerImpl { -public: - TrackBox(uint32_t aTrackType, ISOControl* aControl); - ~TrackBox(); -}; - -// 14496-12 8.1.1 'Media Data Box' -// Box type: 'mdat' -class MediaDataBox : public Box { -public: - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // MediaDataBox methods - uint32_t GetAllSampleSize() { return mAllSampleSize; } - uint32_t FirstSampleOffsetInMediaDataBox() { return mFirstSampleOffset; } - MediaDataBox(uint32_t aTrackType, ISOControl* aControl); - ~MediaDataBox(); - -protected: - uint32_t mAllSampleSize; // All audio and video sample size in this box. - uint32_t mFirstSampleOffset; // The offset of first sample in this box from - // the beginning of this mp4 file. - uint32_t mTrackType; -}; - -// flags for TrackRunBox::flags, 14496-12 8.8.8.1. -#define flags_data_offset_present 0x000001 -#define flags_first_sample_flags_present 0x000002 -#define flags_sample_duration_present 0x000100 -#define flags_sample_size_present 0x000200 -#define flags_sample_flags_present 0x000400 -#define flags_sample_composition_time_offsets_present 0x000800 - -// flag for TrackRunBox::tbl::sample_flags and TrackExtendsBox::default_sample_flags -// which is defined in 14496-12 8.8.3.1. -uint32_t set_sample_flags(bool aSync); - -// 14496-12 8.8.8 'Track Fragment Run Box' -// Box type: 'trun' -class TrackRunBox : public FullBox { -public: - // ISO BMFF members - typedef struct { - uint32_t sample_duration; - uint32_t sample_size; - uint32_t sample_flags; - uint32_t sample_composition_time_offset; - } tbl; - - uint32_t sample_count; - // the following are optional fields - uint32_t data_offset; // data offset exists when audio/video are present in file. - uint32_t first_sample_flags; - UniquePtr<tbl[]> sample_info_table; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // TrackRunBox methods - uint32_t GetAllSampleSize() { return mAllSampleSize; } - nsresult SetDataOffset(uint32_t aOffset); - - TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl); - ~TrackRunBox(); - -protected: - uint32_t fillSampleTable(); - - uint32_t mAllSampleSize; - uint32_t mTrackType; -}; - -// tf_flags in TrackFragmentHeaderBox, 14496-12 8.8.7.1. -#define base_data_offset_present 0x000001 -#define sample_description_index_present 0x000002 -#define default_sample_duration_present 0x000008 -#define default_sample_size_present 0x000010 -#define default_sample_flags_present 0x000020 -#define duration_is_empty 0x010000 -#define default_base_is_moof 0x020000 - -// 14496-12 8.8.7 'Track Fragment Header Box' -// Box type: 'tfhd' -class TrackFragmentHeaderBox : public FullBox { -public: - // ISO BMFF members - uint32_t track_ID; - uint64_t base_data_offset; - uint32_t default_sample_duration; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // TrackFragmentHeaderBox methods - nsresult UpdateBaseDataOffset(uint64_t aOffset); // The offset of the first - // sample in file. - - TrackFragmentHeaderBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl); - ~TrackFragmentHeaderBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.8.6 'Track Fragment Box' -// Box type: 'traf' -// TrackFragmentBox cotains TrackFragmentHeaderBox and TrackRunBox. -class TrackFragmentBox : public DefaultContainerImpl { -public: - TrackFragmentBox(uint32_t aType, ISOControl* aControl); - ~TrackFragmentBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.8.5 'Movie Fragment Header Box' -// Box type: 'mfhd' -class MovieFragmentHeaderBox : public FullBox { -public: - // ISO BMFF members - uint32_t sequence_number; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // MovieFragmentHeaderBox methods - MovieFragmentHeaderBox(uint32_t aType, ISOControl* aControl); - ~MovieFragmentHeaderBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.8.4 'Movie Fragment Box' -// Box type: 'moof' -// MovieFragmentBox contains MovieFragmentHeaderBox and TrackFragmentBox. -class MovieFragmentBox : public DefaultContainerImpl { -public: - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - - // MovieFragmentBox methods - MovieFragmentBox(uint32_t aType, ISOControl* aControl); - ~MovieFragmentBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.8.3 'Track Extends Box' -// Box type: 'trex' -class TrackExtendsBox : public FullBox { -public: - // ISO BMFF members - uint32_t track_ID; - uint32_t default_sample_description_index; - uint32_t default_sample_duration; - uint32_t default_sample_size; - uint32_t default_sample_flags; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // TrackExtendsBox methods - TrackExtendsBox(uint32_t aType, ISOControl* aControl); - ~TrackExtendsBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.8.1 'Movie Extends Box' -// Box type: 'mvex' -// MovieExtendsBox contains TrackExtendsBox. -class MovieExtendsBox : public DefaultContainerImpl { -public: - MovieExtendsBox(ISOControl* aControl); - ~MovieExtendsBox(); -}; - -// 14496-12 8.7.5 'Chunk Offset Box' -// Box type: 'stco' -class ChunkOffsetBox : public FullBox { -public: - // ISO BMFF members - typedef struct { - uint32_t chunk_offset; - } tbl; - - uint32_t entry_count; - UniquePtr<tbl[]> sample_tbl; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // ChunkOffsetBox methods - ChunkOffsetBox(uint32_t aType, ISOControl* aControl); - ~ChunkOffsetBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.7.4 'Sample To Chunk Box' -// Box type: 'stsc' -class SampleToChunkBox : public FullBox { -public: - // ISO BMFF members - typedef struct { - uint32_t first_chunk; - uint32_t sample_per_chunk; - uint32_t sample_description_index; - } tbl; - - uint32_t entry_count; - UniquePtr<tbl[]> sample_tbl; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // SampleToChunkBox methods - SampleToChunkBox(uint32_t aType, ISOControl* aControl); - ~SampleToChunkBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.6.1.2 'Decoding Time to Sample Box' -// Box type: 'stts' -class TimeToSampleBox : public FullBox { -public: - // ISO BMFF members - typedef struct { - uint32_t sample_count; - uint32_t sample_delta; - } tbl; - - uint32_t entry_count; - UniquePtr<tbl[]> sample_tbl; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // TimeToSampleBox methods - TimeToSampleBox(uint32_t aType, ISOControl* aControl); - ~TimeToSampleBox(); - -protected: - uint32_t mTrackType; -}; - -/** - * 14496-12 8.5.2 'Sample Description Box' - * This is the base class for VisualSampleEntry and AudioSampleEntry. - * - * This class is for inherited only, it shouldn't be instanced directly. - * - * The inhertied tree of a codec box should be: - * - * +--> AVCSampleEntry - * +--> VisualSampleEntryBox + - * | +--> ... - * SampleEntryBox + - * | +--> MP4AudioSampleEntry - * +--> AudioSampleEntryBox + - * +--> AMRSampleEntry - * + - * +--> ... - * - */ -class SampleEntryBox : public Box { -public: - // ISO BMFF members - uint8_t reserved[6]; - uint16_t data_reference_index; - - // sampleentrybox methods - SampleEntryBox(const nsACString& aFormat, ISOControl* aControl); - - // MuxerOperation methods - nsresult Write() override; - -protected: - SampleEntryBox() = delete; -}; - -// 14496-12 8.5.2 'Sample Description Box' -// Box type: 'stsd' -class SampleDescriptionBox : public FullBox { -public: - // ISO BMFF members - uint32_t entry_count; - RefPtr<SampleEntryBox> sample_entry_box; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // SampleDescriptionBox methods - SampleDescriptionBox(uint32_t aType, ISOControl* aControl); - ~SampleDescriptionBox(); - -protected: - nsresult CreateAudioSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry); - nsresult CreateVideoSampleEntry(RefPtr<SampleEntryBox>& aSampleEntry); - - uint32_t mTrackType; -}; - -// 14496-12 8.5.2.2 -// The base class for audio codec box. -// This class is for inherited only, it shouldn't be instanced directly. -class AudioSampleEntry : public SampleEntryBox { -public: - // ISO BMFF members - uint16_t sound_version; - uint8_t reserved2[6]; - uint16_t channels; - uint16_t sample_size; - uint16_t compressionId; - uint16_t packet_size; - uint32_t timeScale; // (sample rate of media) <<16 - - // MuxerOperation methods - nsresult Write() override; - - ~AudioSampleEntry(); - -protected: - AudioSampleEntry(const nsACString& aFormat, ISOControl* aControl); -}; - -// 14496-12 8.5.2.2 -// The base class for video codec box. -// This class is for inherited only, it shouldn't be instanced directly. -class VisualSampleEntry : public SampleEntryBox { -public: - // ISO BMFF members - uint8_t reserved[16]; - uint16_t width; - uint16_t height; - - uint32_t horizresolution; // 72 dpi - uint32_t vertresolution; // 72 dpi - uint32_t reserved2; - uint16_t frame_count; // 1, defined in 14496-12 8.5.2.2 - - uint8_t compressorName[32]; - uint16_t depth; // 0x0018, defined in 14496-12 8.5.2.2; - uint16_t pre_defined; // -1, defined in 14496-12 8.5.2.2; - - // MuxerOperation methods - nsresult Write() override; - - // VisualSampleEntry methods - ~VisualSampleEntry(); - -protected: - VisualSampleEntry(const nsACString& aFormat, ISOControl* aControl); -}; - -// 14496-12 8.7.3.2 'Sample Size Box' -// Box type: 'stsz' -class SampleSizeBox : public FullBox { -public: - // ISO BMFF members - uint32_t sample_size; - uint32_t sample_count; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // SampleSizeBox methods - SampleSizeBox(ISOControl* aControl); - ~SampleSizeBox(); -}; - -// 14496-12 8.5.1 'Sample Table Box' -// Box type: 'stbl' -// -// SampleTableBox contains SampleDescriptionBox, -// TimeToSampleBox, -// SampleToChunkBox, -// SampleSizeBox and -// ChunkOffsetBox. -class SampleTableBox : public DefaultContainerImpl { -public: - SampleTableBox(uint32_t aType, ISOControl* aControl); - ~SampleTableBox(); -}; - -// 14496-12 8.7.2 'Data Reference Box' -// Box type: 'url ' -class DataEntryUrlBox : public FullBox { -public: - // ISO BMFF members - // flags in DataEntryUrlBox::flags - const static uint16_t flags_media_at_the_same_file = 0x0001; - - nsCString location; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // DataEntryUrlBox methods - DataEntryUrlBox(); - DataEntryUrlBox(ISOControl* aControl); - DataEntryUrlBox(const DataEntryUrlBox& aBox); - ~DataEntryUrlBox(); -}; - -// 14496-12 8.7.2 'Data Reference Box' -// Box type: 'dref' -class DataReferenceBox : public FullBox { -public: - // ISO BMFF members - uint32_t entry_count; - nsTArray<nsAutoPtr<DataEntryUrlBox>> urls; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // DataReferenceBox methods - DataReferenceBox(ISOControl* aControl); - ~DataReferenceBox(); -}; - -// 14496-12 8.7.1 'Data Information Box' -// Box type: 'dinf' -// DataInformationBox contains DataReferenceBox. -class DataInformationBox : public DefaultContainerImpl { -public: - DataInformationBox(ISOControl* aControl); - ~DataInformationBox(); -}; - -// 14496-12 8.4.5.2 'Video Media Header Box' -// Box type: 'vmhd' -class VideoMediaHeaderBox : public FullBox { -public: - // ISO BMFF members - uint16_t graphicsmode; - uint16_t opcolor[3]; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // VideoMediaHeaderBox methods - VideoMediaHeaderBox(ISOControl* aControl); - ~VideoMediaHeaderBox(); -}; - -// 14496-12 8.4.5.3 'Sound Media Header Box' -// Box type: 'smhd' -class SoundMediaHeaderBox : public FullBox { -public: - // ISO BMFF members - uint16_t balance; - uint16_t reserved; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // SoundMediaHeaderBox methods - SoundMediaHeaderBox(ISOControl* aControl); - ~SoundMediaHeaderBox(); -}; - -// 14496-12 8.4.4 'Media Information Box' -// Box type: 'minf' -// MediaInformationBox contains SoundMediaHeaderBox, DataInformationBox and -// SampleTableBox. -class MediaInformationBox : public DefaultContainerImpl { -public: - MediaInformationBox(uint32_t aType, ISOControl* aControl); - ~MediaInformationBox(); - -protected: - uint32_t mTrackType; -}; - -// flags for TrackHeaderBox::flags. -#define flags_track_enabled 0x000001 -#define flags_track_in_movie 0x000002 -#define flags_track_in_preview 0x000004 - -// 14496-12 8.3.2 'Track Header Box' -// Box type: 'tkhd' -class TrackHeaderBox : public FullBox { -public: - // ISO BMFF members - // version = 0 - uint32_t creation_time; - uint32_t modification_time; - uint32_t track_ID; - uint32_t reserved; - uint32_t duration; - - uint32_t reserved2[2]; - uint16_t layer; - uint16_t alternate_group; - uint16_t volume; - uint16_t reserved3; - uint32_t matrix[9]; - uint32_t width; - uint32_t height; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // TrackHeaderBox methods - TrackHeaderBox(uint32_t aType, ISOControl* aControl); - ~TrackHeaderBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.4.3 'Handler Reference Box' -// Box type: 'hdlr' -class HandlerBox : public FullBox { -public: - // ISO BMFF members - uint32_t pre_defined; - uint32_t handler_type; - uint32_t reserved[3]; - nsCString name; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // HandlerBox methods - HandlerBox(uint32_t aType, ISOControl* aControl); - ~HandlerBox(); - -protected: - uint32_t mTrackType; -}; - -// 14496-12 8.4.1 'Media Box' -// Box type: 'mdia' -// MediaBox contains MediaHeaderBox, HandlerBox, and MediaInformationBox. -class MediaBox : public DefaultContainerImpl { -public: - MediaBox(uint32_t aType, ISOControl* aControl); - ~MediaBox(); - -protected: - uint32_t mTrackType; -}; - -} -#endif // ISOMediaBoxes_h_ diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp b/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp deleted file mode 100644 index fa23616e9..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 "ISOMediaWriter.h" -#include "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "ISOTrackMetadata.h" -#include "nsThreadUtils.h" -#include "MediaEncoder.h" -#include "VideoUtils.h" -#include "GeckoProfiler.h" - -#undef LOG -#ifdef MOZ_WIDGET_GONK -#include <android/log.h> -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args); -#else -#define LOG(args, ...) -#endif - -namespace mozilla { - -const static uint32_t FRAG_DURATION = 2 * USECS_PER_S; // microsecond per unit - -ISOMediaWriter::ISOMediaWriter(uint32_t aType, uint32_t aHint) - : ContainerWriter() - , mState(MUXING_HEAD) - , mBlobReady(false) - , mType(0) -{ - if (aType & CREATE_AUDIO_TRACK) { - mType |= Audio_Track; - } - if (aType & CREATE_VIDEO_TRACK) { - mType |= Video_Track; - } - mControl = new ISOControl(aHint); - MOZ_COUNT_CTOR(ISOMediaWriter); -} - -ISOMediaWriter::~ISOMediaWriter() -{ - MOZ_COUNT_DTOR(ISOMediaWriter); -} - -nsresult -ISOMediaWriter::RunState() -{ - nsresult rv; - switch (mState) { - case MUXING_HEAD: - { - rv = mControl->GenerateFtyp(); - NS_ENSURE_SUCCESS(rv, rv); - rv = mControl->GenerateMoov(); - NS_ENSURE_SUCCESS(rv, rv); - mState = MUXING_FRAG; - break; - } - case MUXING_FRAG: - { - rv = mControl->GenerateMoof(mType); - NS_ENSURE_SUCCESS(rv, rv); - - bool EOS; - if (ReadyToRunState(EOS) && EOS) { - mState = MUXING_DONE; - } - break; - } - case MUXING_DONE: - { - break; - } - } - mBlobReady = true; - return NS_OK; -} - -nsresult -ISOMediaWriter::WriteEncodedTrack(const EncodedFrameContainer& aData, - uint32_t aFlags) -{ - PROFILER_LABEL("ISOMediaWriter", "WriteEncodedTrack", - js::ProfileEntry::Category::OTHER); - // Muxing complete, it doesn't allowed to reentry again. - if (mState == MUXING_DONE) { - MOZ_ASSERT(false); - return NS_ERROR_FAILURE; - } - - FragmentBuffer* frag = nullptr; - uint32_t len = aData.GetEncodedFrames().Length(); - - if (!len) { - // no frame? why bother to WriteEncodedTrack - return NS_OK; - } - for (uint32_t i = 0; i < len; i++) { - RefPtr<EncodedFrame> frame(aData.GetEncodedFrames()[i]); - EncodedFrame::FrameType type = frame->GetFrameType(); - if (type == EncodedFrame::AAC_AUDIO_FRAME || - type == EncodedFrame::AAC_CSD || - type == EncodedFrame::AMR_AUDIO_FRAME || - type == EncodedFrame::AMR_AUDIO_CSD || - type == EncodedFrame::EVRC_AUDIO_FRAME || - type == EncodedFrame::EVRC_AUDIO_CSD) { - frag = mAudioFragmentBuffer; - } else if (type == EncodedFrame::AVC_I_FRAME || - type == EncodedFrame::AVC_P_FRAME || - type == EncodedFrame::AVC_B_FRAME || - type == EncodedFrame::AVC_CSD) { - frag = mVideoFragmentBuffer; - } else { - MOZ_ASSERT(0); - return NS_ERROR_FAILURE; - } - - frag->AddFrame(frame); - } - - // Encoder should send CSD (codec specific data) frame before sending the - // audio/video frames. When CSD data is ready, it is sufficient to generate a - // moov data. If encoder doesn't send CSD yet, muxer needs to wait before - // generating anything. - if (mType & Audio_Track && (!mAudioFragmentBuffer || - !mAudioFragmentBuffer->HasCSD())) { - return NS_OK; - } - if (mType & Video_Track && (!mVideoFragmentBuffer || - !mVideoFragmentBuffer->HasCSD())) { - return NS_OK; - } - - // Only one FrameType in EncodedFrameContainer so it doesn't need to be - // inside the for-loop. - if (frag && (aFlags & END_OF_STREAM)) { - frag->SetEndOfStream(); - } - - nsresult rv; - bool EOS; - if (ReadyToRunState(EOS)) { - // Because track encoder won't generate new data after EOS, it needs to make - // sure the state reaches MUXING_DONE when EOS is signaled. - do { - rv = RunState(); - } while (EOS && mState != MUXING_DONE); - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; -} - -bool -ISOMediaWriter::ReadyToRunState(bool& aEOS) -{ - aEOS = false; - bool bReadyToMux = true; - if ((mType & Audio_Track) && (mType & Video_Track)) { - if (!mAudioFragmentBuffer->HasEnoughData()) { - bReadyToMux = false; - } - if (!mVideoFragmentBuffer->HasEnoughData()) { - bReadyToMux = false; - } - - if (mAudioFragmentBuffer->EOS() && mVideoFragmentBuffer->EOS()) { - aEOS = true; - bReadyToMux = true; - } - } else if (mType == Audio_Track) { - if (!mAudioFragmentBuffer->HasEnoughData()) { - bReadyToMux = false; - } - if (mAudioFragmentBuffer->EOS()) { - aEOS = true; - bReadyToMux = true; - } - } else if (mType == Video_Track) { - if (!mVideoFragmentBuffer->HasEnoughData()) { - bReadyToMux = false; - } - if (mVideoFragmentBuffer->EOS()) { - aEOS = true; - bReadyToMux = true; - } - } - - return bReadyToMux; -} - -nsresult -ISOMediaWriter::GetContainerData(nsTArray<nsTArray<uint8_t>>* aOutputBufs, - uint32_t aFlags) -{ - PROFILER_LABEL("ISOMediaWriter", "GetContainerData", - js::ProfileEntry::Category::OTHER); - if (mBlobReady) { - if (mState == MUXING_DONE) { - mIsWritingComplete = true; - } - mBlobReady = false; - return mControl->GetBufs(aOutputBufs); - } - return NS_OK; -} - -nsresult -ISOMediaWriter::SetMetadata(TrackMetadataBase* aMetadata) -{ - PROFILER_LABEL("ISOMediaWriter", "SetMetadata", - js::ProfileEntry::Category::OTHER); - if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AAC || - aMetadata->GetKind() == TrackMetadataBase::METADATA_AMR || - aMetadata->GetKind() == TrackMetadataBase::METADATA_EVRC) { - mControl->SetMetadata(aMetadata); - mAudioFragmentBuffer = new FragmentBuffer(Audio_Track, FRAG_DURATION); - mControl->SetFragment(mAudioFragmentBuffer); - return NS_OK; - } - if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AVC) { - mControl->SetMetadata(aMetadata); - mVideoFragmentBuffer = new FragmentBuffer(Video_Track, FRAG_DURATION); - mControl->SetFragment(mVideoFragmentBuffer); - return NS_OK; - } - - return NS_ERROR_FAILURE; -} - -} // namespace mozilla diff --git a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h b/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h deleted file mode 100644 index cccbbe3cb..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOMediaWriter.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 ISOMediaWriter_h_ -#define ISOMediaWriter_h_ - -#include "ContainerWriter.h" -#include "nsAutoPtr.h" -#include "nsIRunnable.h" - -namespace mozilla { - -class ISOControl; -class FragmentBuffer; - -class ISOMediaWriter : public ContainerWriter -{ -public: - // Generate an fragmented MP4 stream, ISO/IEC 14496-12. - // Brand names in 'ftyp' box are 'isom' and 'mp42'. - const static uint32_t TYPE_FRAG_MP4 = 1 << 0; - - // Generate an fragmented 3GP stream, 3GPP TS 26.244, - // '5.4.3 Basic profile'. - // Brand names in 'ftyp' box are '3gp9' and 'isom'. - const static uint32_t TYPE_FRAG_3GP = 1 << 1; - - // Generate an fragmented 3G2 stream, 3GPP2 C.S0050-B - // Brand names in 'ftyp' box are '3g2c' and 'isom' - const static uint32_t TYPE_FRAG_3G2 = 1 << 2; - - // aType is the combination of CREATE_AUDIO_TRACK and CREATE_VIDEO_TRACK. - // It is a hint to muxer that the output streaming contains audio, video - // or both. - // - // aHint is one of the value in TYPE_XXXXXXXX. It is a hint to muxer what kind - // of ISO format should be generated. - ISOMediaWriter(uint32_t aType, uint32_t aHint = TYPE_FRAG_MP4); - ~ISOMediaWriter(); - - // ContainerWriter methods - nsresult WriteEncodedTrack(const EncodedFrameContainer &aData, - uint32_t aFlags = 0) override; - - nsresult GetContainerData(nsTArray<nsTArray<uint8_t>>* aOutputBufs, - uint32_t aFlags = 0) override; - - nsresult SetMetadata(TrackMetadataBase* aMetadata) override; - -protected: - /** - * The state of each state will generate one or more blob. - * Each blob will be a moov, moof, moof... until receiving EOS. - * The generated sequence is: - * - * moov -> moof -> moof -> ... -> moof -> moof - * - * Following is the details of each state. - * MUXING_HEAD: - * It collects the metadata to generate a moov. The state transits to - * MUXING_HEAD after output moov blob. - * - * MUXING_FRAG: - * It collects enough audio/video data to generate a fragment blob. This - * will be repeated until END_OF_STREAM and then transiting to MUXING_DONE. - * - * MUXING_DONE: - * End of ISOMediaWriter life cycle. - */ - enum MuxState { - MUXING_HEAD, - MUXING_FRAG, - MUXING_DONE, - }; - -private: - nsresult RunState(); - - // True if one of following conditions hold: - // 1. Audio/Video accumulates enough data to generate a moof. - // 2. Get EOS signal. - // aEOS will be assigned to true if it gets EOS signal. - bool ReadyToRunState(bool& aEOS); - - // The main class to generate and iso box. Its life time is same as - // ISOMediaWriter and deleted only if ISOMediaWriter is destroyed. - nsAutoPtr<ISOControl> mControl; - - // Buffers to keep audio/video data frames, they are created when metadata is - // received. Only one instance for each media type is allowed and they will be - // deleted only if ISOMediaWriter is destroyed. - nsAutoPtr<FragmentBuffer> mAudioFragmentBuffer; - nsAutoPtr<FragmentBuffer> mVideoFragmentBuffer; - - MuxState mState; - - // A flag to indicate the output buffer is ready to blob out. - bool mBlobReady; - - // Combination of Audio_Track or Video_Track. - uint32_t mType; -}; - -} // namespace mozilla - -#endif // ISOMediaWriter_h_ diff --git a/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h b/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h deleted file mode 100644 index 3613e1e9e..000000000 --- a/dom/media/encoder/fmp4_muxer/ISOTrackMetadata.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 ISOTrackMetadata_h_ -#define ISOTrackMetadata_h_ - -#include "TrackMetadataBase.h" - -namespace mozilla { - -class AACTrackMetadata : public AudioTrackMetadata { -public: - // AudioTrackMetadata members - uint32_t GetAudioFrameDuration() override { return mFrameDuration; } - uint32_t GetAudioFrameSize() override { return mFrameSize; } - uint32_t GetAudioSampleRate() override { return mSampleRate; } - uint32_t GetAudioChannels() override { return mChannels; } - - // TrackMetadataBase member - MetadataKind GetKind() const override { return METADATA_AAC; } - - // AACTrackMetadata members - AACTrackMetadata() - : mSampleRate(0) - , mFrameDuration(0) - , mFrameSize(0) - , mChannels(0) { - MOZ_COUNT_CTOR(AACTrackMetadata); - } - ~AACTrackMetadata() { MOZ_COUNT_DTOR(AACTrackMetadata); } - - uint32_t mSampleRate; // From 14496-3 table 1.16, it could be 7350 ~ 96000. - uint32_t mFrameDuration; // Audio frame duration based on SampleRate. - uint32_t mFrameSize; // Audio frame size, 0 is variant size. - uint32_t mChannels; // Channel number, it should be 1 or 2. -}; - -// AVC clock rate is 90k Hz. -#define AVC_CLOCK_RATE 90000 - -class AVCTrackMetadata : public VideoTrackMetadata { -public: - // VideoTrackMetadata members - uint32_t GetVideoHeight() override { return mHeight; } - uint32_t GetVideoWidth() override {return mWidth; } - uint32_t GetVideoDisplayHeight() override { return mDisplayHeight; } - uint32_t GetVideoDisplayWidth() override { return mDisplayWidth; } - uint32_t GetVideoClockRate() override { return AVC_CLOCK_RATE; } - uint32_t GetVideoFrameRate() override { return mFrameRate; } - - // TrackMetadataBase member - MetadataKind GetKind() const override { return METADATA_AVC; } - - // AVCTrackMetadata - AVCTrackMetadata() - : mHeight(0) - , mWidth(0) - , mDisplayHeight(0) - , mDisplayWidth(0) - , mFrameRate(0) { - MOZ_COUNT_CTOR(AVCTrackMetadata); - } - ~AVCTrackMetadata() { MOZ_COUNT_DTOR(AVCTrackMetadata); } - - uint32_t mHeight; - uint32_t mWidth; - uint32_t mDisplayHeight; - uint32_t mDisplayWidth; - uint32_t mFrameRate; // frames per second -}; - - -// AMR sample rate is 8000 samples/s. -#define AMR_SAMPLE_RATE 8000 - -// Channel number is always 1. -#define AMR_CHANNELS 1 - -// AMR speech codec, 3GPP TS 26.071. Encoder and continer support AMR-NB only -// currently. -class AMRTrackMetadata : public AudioTrackMetadata { -public: - // AudioTrackMetadata members - // - // The number of sample sets generates by encoder is variant. So the - // frame duration and frame size are both 0. - uint32_t GetAudioFrameDuration() override { return 0; } - uint32_t GetAudioFrameSize() override { return 0; } - uint32_t GetAudioSampleRate() override { return AMR_SAMPLE_RATE; } - uint32_t GetAudioChannels() override { return AMR_CHANNELS; } - - // TrackMetadataBase member - MetadataKind GetKind() const override { return METADATA_AMR; } - - // AMRTrackMetadata members - AMRTrackMetadata() { MOZ_COUNT_CTOR(AMRTrackMetadata); } - ~AMRTrackMetadata() { MOZ_COUNT_DTOR(AMRTrackMetadata); } -}; - -// EVRC sample rate is 8000 samples/s. -#define EVRC_SAMPLE_RATE 8000 - -class EVRCTrackMetadata : public AudioTrackMetadata { -public: - // AudioTrackMetadata members - // - // The number of sample sets generates by encoder is variant. So the - // frame duration and frame size are both 0. - uint32_t GetAudioFrameDuration() override { return 0; } - uint32_t GetAudioFrameSize() override { return 0; } - uint32_t GetAudioSampleRate() override { return EVRC_SAMPLE_RATE; } - uint32_t GetAudioChannels() override { return mChannels; } - - // TrackMetadataBase member - MetadataKind GetKind() const override { return METADATA_EVRC; } - - // EVRCTrackMetadata members - EVRCTrackMetadata() - : mChannels(0) { - MOZ_COUNT_CTOR(EVRCTrackMetadata); - } - ~EVRCTrackMetadata() { MOZ_COUNT_DTOR(EVRCTrackMetadata); } - - uint32_t mChannels; // Channel number, it should be 1 or 2. -}; - -} - -#endif // ISOTrackMetadata_h_ diff --git a/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp b/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp deleted file mode 100644 index 72880b5cb..000000000 --- a/dom/media/encoder/fmp4_muxer/MP4ESDS.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 <climits> -#include "ISOControl.h" -#include "ISOMediaBoxes.h" -#include "MP4ESDS.h" - -namespace mozilla { - -nsresult -MP4AudioSampleEntry::Generate(uint32_t* aBoxSize) -{ - uint32_t box_size; - nsresult rv = es->Generate(&box_size); - NS_ENSURE_SUCCESS(rv, rv); - size += box_size; - - *aBoxSize = size; - return NS_OK; -} - -nsresult -MP4AudioSampleEntry::Write() -{ - BoxSizeChecker checker(mControl, size); - nsresult rv; - rv = AudioSampleEntry::Write(); - NS_ENSURE_SUCCESS(rv, rv); - rv = es->Write(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -MP4AudioSampleEntry::MP4AudioSampleEntry(ISOControl* aControl) - : AudioSampleEntry(NS_LITERAL_CSTRING("mp4a"), aControl) -{ - es = new ESDBox(aControl); - MOZ_COUNT_CTOR(MP4AudioSampleEntry); -} - -MP4AudioSampleEntry::~MP4AudioSampleEntry() -{ - MOZ_COUNT_DTOR(MP4AudioSampleEntry); -} - -nsresult -ESDBox::Generate(uint32_t* aBoxSize) -{ - uint32_t box_size; - es_descriptor->Generate(&box_size); - size += box_size; - *aBoxSize = size; - return NS_OK; -} - -nsresult -ESDBox::Write() -{ - WRITE_FULLBOX(mControl, size) - es_descriptor->Write(); - return NS_OK; -} - -ESDBox::ESDBox(ISOControl* aControl) - : FullBox(NS_LITERAL_CSTRING("esds"), 0, 0, aControl) -{ - es_descriptor = new ES_Descriptor(aControl); - MOZ_COUNT_CTOR(ESDBox); -} - -ESDBox::~ESDBox() -{ - MOZ_COUNT_DTOR(ESDBox); -} - -nsresult -ES_Descriptor::Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) -{ - // ES_Descriptor is not a real ISOMediaBox, so we return nothing here. - return NS_OK; -} - -nsresult -ES_Descriptor::Write() -{ - mControl->Write(tag); - mControl->Write(length); - mControl->Write(ES_ID); - mControl->WriteBits(streamDependenceFlag.to_ulong(), streamDependenceFlag.size()); - mControl->WriteBits(URL_Flag.to_ulong(), URL_Flag.size()); - mControl->WriteBits(reserved.to_ulong(), reserved.size()); - mControl->WriteBits(streamPriority.to_ulong(), streamPriority.size()); - mControl->Write(DecodeSpecificInfo.Elements(), DecodeSpecificInfo.Length()); - - return NS_OK; -} - -nsresult -ES_Descriptor::Generate(uint32_t* aBoxSize) -{ - nsresult rv; - // 14496-1 '8.3.4 DecoderConfigDescriptor' - // 14496-1 '10.2.3 SL Packet Header Configuration' - FragmentBuffer* frag = mControl->GetFragment(Audio_Track); - rv = frag->GetCSD(DecodeSpecificInfo); - NS_ENSURE_SUCCESS(rv, rv); - - length = sizeof(ES_ID) + 1; - length += DecodeSpecificInfo.Length(); - - *aBoxSize = sizeof(tag) + sizeof(length) + length; - return NS_OK; -} - -ES_Descriptor::ES_Descriptor(ISOControl* aControl) - : tag(ESDescrTag) - , length(0) - , ES_ID(0) - , streamDependenceFlag(0) - , URL_Flag(0) - , reserved(0) - , streamPriority(0) - , mControl(aControl) -{ - MOZ_COUNT_CTOR(ES_Descriptor); -} - -ES_Descriptor::~ES_Descriptor() -{ - MOZ_COUNT_DTOR(ES_Descriptor); -} - -} diff --git a/dom/media/encoder/fmp4_muxer/MP4ESDS.h b/dom/media/encoder/fmp4_muxer/MP4ESDS.h deleted file mode 100644 index ee91312c1..000000000 --- a/dom/media/encoder/fmp4_muxer/MP4ESDS.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 MP4ESDS_h_ -#define MP4ESDS_h_ - -#include "nsTArray.h" -#include "MuxerOperation.h" - -namespace mozilla { - -class ISOControl; - -/** - * ESDS tag - */ -#define ESDescrTag 0x03 - -/** - * 14496-1 '8.3.3 ES_Descriptor'. - * It will get DecoderConfigDescriptor and SLConfigDescriptor from - * AAC CSD data. - */ -class ES_Descriptor : public MuxerOperation { -public: - // ISO BMFF members - uint8_t tag; // ESDescrTag - uint8_t length; - uint16_t ES_ID; - std::bitset<1> streamDependenceFlag; - std::bitset<1> URL_Flag; - std::bitset<1> reserved; - std::bitset<5> streamPriority; - - nsTArray<uint8_t> DecodeSpecificInfo; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - nsresult Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) override; - - // ES_Descriptor methods - ES_Descriptor(ISOControl* aControl); - ~ES_Descriptor(); - -protected: - ISOControl* mControl; -}; - -// 14496-14 5.6 'Sample Description Boxes' -// Box type: 'esds' -class ESDBox : public FullBox { -public: - // ISO BMFF members - RefPtr<ES_Descriptor> es_descriptor; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // ESDBox methods - ESDBox(ISOControl* aControl); - ~ESDBox(); -}; - -// 14496-14 5.6 'Sample Description Boxes' -// Box type: 'mp4a' -class MP4AudioSampleEntry : public AudioSampleEntry { -public: - // ISO BMFF members - RefPtr<ESDBox> es; - - // MuxerOperation methods - nsresult Generate(uint32_t* aBoxSize) override; - nsresult Write() override; - - // MP4AudioSampleEntry methods - MP4AudioSampleEntry(ISOControl* aControl); - ~MP4AudioSampleEntry(); -}; - -} - -#endif // MP4ESDS_h_ diff --git a/dom/media/encoder/fmp4_muxer/MuxerOperation.h b/dom/media/encoder/fmp4_muxer/MuxerOperation.h deleted file mode 100644 index 0b83c89b0..000000000 --- a/dom/media/encoder/fmp4_muxer/MuxerOperation.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ -/* 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 "nsString.h" -#include "nsTArray.h" - -#ifndef MuxerOperation_h_ -#define MuxerOperation_h_ - -namespace mozilla { - -/** - * The interface for ISO box. All Boxes inherit from this interface. - * Generate() and Write() are needed to be called to produce a complete box. - * - * Generate() will generate all the data structures and their size. - * - * Write() will write all data into muxing output stream (ISOControl actually) - * and update the data which can't be known at Generate() (for example, the - * offset of the video data in mp4 file). - * - * ISO base media format is composed of several container boxes and the contained - * boxes. The container boxes hold a list of MuxerOperation which is implemented - * by contained boxes. The contained boxes will be called via the list. - * For example: - * MovieBox (container) ---> boxes (array of MuxerOperation) - * |---> MovieHeaderBox (full box) - * |---> TrakBox (container) - * |---> MovieExtendsBox (container) - * - * The complete box structure can be found at 14496-12 E.2 "The‘isom’brand". - */ -class MuxerOperation { -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MuxerOperation) - - // Generate data of this box and its contained box, and calculate box size. - virtual nsresult Generate(uint32_t* aBoxSize) = 0; - - // Write data to stream. - virtual nsresult Write() = 0; - - // Find the box type via its name (name is the box type defined in 14496-12; - // for example, 'moov' is the name of MovieBox). - // It can only look child boxes including itself and the box in the boxes - // list if exists. It can't look parent boxes. - virtual nsresult Find(const nsACString& aType, - nsTArray<RefPtr<MuxerOperation>>& aOperations) = 0; - -protected: - virtual ~MuxerOperation() {} -}; - -} -#endif diff --git a/dom/media/encoder/fmp4_muxer/moz.build b/dom/media/encoder/fmp4_muxer/moz.build deleted file mode 100644 index 5ff274be5..000000000 --- a/dom/media/encoder/fmp4_muxer/moz.build +++ /dev/null @@ -1,22 +0,0 @@ -# -*- 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/. - -EXPORTS += [ - 'ISOMediaWriter.h', - 'ISOTrackMetadata.h', -] - -UNIFIED_SOURCES += [ - 'AMRBox.cpp', - 'AVCBox.cpp', - 'EVRCBox.cpp', - 'ISOControl.cpp', - 'ISOMediaBoxes.cpp', - 'ISOMediaWriter.cpp', - 'MP4ESDS.cpp', -] - -FINAL_LIBRARY = 'xul' diff --git a/dom/media/encoder/moz.build b/dom/media/encoder/moz.build index 0d5cdc16f..f29430cb0 100644 --- a/dom/media/encoder/moz.build +++ b/dom/media/encoder/moz.build @@ -7,9 +7,6 @@ with Files('*'): BUG_COMPONENT = ('Core', 'Video/Audio: Recording') -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - DIRS += ['fmp4_muxer'] - EXPORTS += [ 'ContainerWriter.h', 'EncodedFrameContainer.h', @@ -37,16 +34,6 @@ FINAL_LIBRARY = 'xul' # These includes are from Android JB, for use of MediaCodec. LOCAL_INCLUDES += ['/ipc/chromium/src'] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '15': - LOCAL_INCLUDES += [ - '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [ - 'frameworks/av/include/media', - 'frameworks/native/include', - 'frameworks/native/opengl/include', - ] - - ] - include('/ipc/chromium/chromium-config.mozbuild') # Suppress some GCC warnings being treated as errors: diff --git a/dom/media/gmp/GMPServiceParent.cpp b/dom/media/gmp/GMPServiceParent.cpp index b58ab8853..2b4831cd6 100644 --- a/dom/media/gmp/GMPServiceParent.cpp +++ b/dom/media/gmp/GMPServiceParent.cpp @@ -270,11 +270,7 @@ GeckoMediaPluginServiceParent::InitStorage() // Directory service is main thread only, so cache the profile dir here // so that we can use it off main thread. -#ifdef MOZ_WIDGET_GONK - nsresult rv = NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla"), false, getter_AddRefs(mStorageBaseDir)); -#else nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir)); -#endif if (NS_WARN_IF(NS_FAILED(rv))) { return rv; diff --git a/dom/media/moz.build b/dom/media/moz.build index d1885793b..4d036a5f6 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -169,11 +169,6 @@ IPDL_SOURCES += [ 'webrtc/PWebrtcGlobal.ipdl' ] -if CONFIG['MOZ_B2G']: - EXPORTS.mozilla += [ - 'MediaPermissionGonk.h', - ] - EXPORTS.mozilla.dom += [ 'AudioStreamTrack.h', 'AudioTrack.h', @@ -270,11 +265,6 @@ UNIFIED_SOURCES += [ if CONFIG['OS_TARGET'] == 'WINNT': SOURCES += [ 'ThreadPoolCOMListener.cpp' ] -if CONFIG['MOZ_B2G']: - SOURCES += [ - 'MediaPermissionGonk.cpp', - ] - # DecoderTraits.cpp needs to be built separately because of Mac OS X headers. SOURCES += [ 'DecoderTraits.cpp', @@ -325,9 +315,6 @@ else: if CONFIG['ANDROID_VERSION'] > '15': DEFINES['MOZ_OMX_WEBM_DECODER'] = True -if CONFIG['MOZ_GONK_MEDIACODEC']: - DEFINES['MOZ_GONK_MEDIACODEC'] = True - include('/ipc/chromium/chromium-config.mozbuild') # Suppress some GCC warnings being treated as errors: diff --git a/dom/media/ogg/OggCodecState.cpp b/dom/media/ogg/OggCodecState.cpp index 6830639e8..e7e1ca4a3 100644 --- a/dom/media/ogg/OggCodecState.cpp +++ b/dom/media/ogg/OggCodecState.cpp @@ -18,18 +18,6 @@ #include <opus/opus.h> #include "opus/opus_multistream.h" -// On Android JellyBean, the hardware.h header redefines version_major and -// version_minor, which breaks our build. See: -// https://bugzilla.mozilla.org/show_bug.cgi?id=912702#c6 -#ifdef MOZ_WIDGET_GONK -#ifdef version_major -#undef version_major -#endif -#ifdef version_minor -#undef version_minor -#endif -#endif - namespace mozilla { extern LazyLogModule gMediaDecoderLog; diff --git a/dom/media/ogg/OggWriter.cpp b/dom/media/ogg/OggWriter.cpp index bb0dca67b..e1aa93eaf 100644 --- a/dom/media/ogg/OggWriter.cpp +++ b/dom/media/ogg/OggWriter.cpp @@ -7,12 +7,7 @@ #include "GeckoProfiler.h" #undef LOG -#ifdef MOZ_WIDGET_GONK -#include <android/log.h> -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "MediaEncoder", ## args); -#else #define LOG(args, ...) -#endif namespace mozilla { diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp b/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp deleted file mode 100644 index 0bc3fbea9..000000000 --- a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "MediaCodecProxy.h" -#include <OMX_IVCommon.h> -#include <gui/Surface.h> -#include <ICrypto.h> -#include "GonkAudioDecoderManager.h" -#include "MediaDecoderReader.h" -#include "VideoUtils.h" -#include "nsTArray.h" -#include "mozilla/Logging.h" -#include "stagefright/MediaBuffer.h" -#include "stagefright/MetaData.h" -#include "stagefright/MediaErrors.h" -#include <stagefright/foundation/AMessage.h> -#include <stagefright/foundation/ALooper.h> -#include "media/openmax/OMX_Audio.h" -#include "MediaData.h" -#include "MediaInfo.h" - -#define CODECCONFIG_TIMEOUT_US 10000LL -#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL - -#include <android/log.h> -#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__) - -#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) - -using namespace android; -typedef android::MediaCodecProxy MediaCodecProxy; - -namespace mozilla { - -GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig) - : mAudioChannels(aConfig.mChannels) - , mAudioRate(aConfig.mRate) - , mAudioProfile(aConfig.mProfile) - , mAudioCompactor(mAudioQueue) -{ - MOZ_COUNT_CTOR(GonkAudioDecoderManager); - MOZ_ASSERT(mAudioChannels); - mCodecSpecificData = aConfig.mCodecSpecificConfig; - mMimeType = aConfig.mMimeType; -} - -GonkAudioDecoderManager::~GonkAudioDecoderManager() -{ - MOZ_COUNT_DTOR(GonkAudioDecoderManager); -} - -RefPtr<MediaDataDecoder::InitPromise> -GonkAudioDecoderManager::Init() -{ - if (InitMediaCodecProxy()) { - return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__); - } else { - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } -} - -bool -GonkAudioDecoderManager::InitMediaCodecProxy() -{ - status_t rv = OK; - if (!InitLoopers(MediaData::AUDIO_DATA)) { - return false; - } - - mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false); - if (!mDecoder.get()) { - return false; - } - if (!mDecoder->AllocateAudioMediaCodec()) - { - mDecoder = nullptr; - return false; - } - sp<AMessage> format = new AMessage; - // Fixed values - GADM_LOG("Configure audio mime type:%s, chan no:%d, sample-rate:%d, profile:%d", - mMimeType.get(), mAudioChannels, mAudioRate, mAudioProfile); - format->setString("mime", mMimeType.get()); - format->setInt32("channel-count", mAudioChannels); - format->setInt32("sample-rate", mAudioRate); - format->setInt32("aac-profile", mAudioProfile); - status_t err = mDecoder->configure(format, nullptr, nullptr, 0); - if (err != OK || !mDecoder->Prepare()) { - return false; - } - - if (mMimeType.EqualsLiteral("audio/mp4a-latm")) { - rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0, - android::MediaCodec::BUFFER_FLAG_CODECCONFIG, - CODECCONFIG_TIMEOUT_US); - } - - if (rv == OK) { - return true; - } else { - GADM_LOG("Failed to input codec specific data!"); - return false; - } -} - -nsresult -GonkAudioDecoderManager::CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset) -{ - if (!(aBuffer != nullptr && aBuffer->data() != nullptr)) { - GADM_LOG("Audio Buffer is not valid!"); - return NS_ERROR_UNEXPECTED; - } - - int64_t timeUs; - if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - return NS_ERROR_UNEXPECTED; - } - - if (aBuffer->range_length() == 0) { - // Some decoders may return spurious empty buffers that we just want to ignore - // quoted from Android's AwesomePlayer.cpp - return NS_ERROR_NOT_AVAILABLE; - } - - if (mLastTime > timeUs) { - GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs); - MOZ_ASSERT(false); - return NS_ERROR_NOT_AVAILABLE; - } - mLastTime = timeUs; - - const uint8_t *data = static_cast<const uint8_t*>(aBuffer->data()); - size_t dataOffset = aBuffer->range_offset(); - size_t size = aBuffer->range_length(); - - uint32_t frames = size / (2 * mAudioChannels); - - CheckedInt64 duration = FramesToUsecs(frames, mAudioRate); - if (!duration.isValid()) { - return NS_ERROR_UNEXPECTED; - } - - typedef AudioCompactor::NativeCopy OmxCopy; - mAudioCompactor.Push(aStreamOffset, - timeUs, - mAudioRate, - frames, - mAudioChannels, - OmxCopy(data+dataOffset, - size, - mAudioChannels)); - return NS_OK; -} - -nsresult -GonkAudioDecoderManager::Output(int64_t aStreamOffset, - RefPtr<MediaData>& aOutData) -{ - aOutData = nullptr; - if (mAudioQueue.GetSize() > 0) { - aOutData = mAudioQueue.PopFront(); - return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK; - } - - status_t err; - MediaBuffer* audioBuffer = nullptr; - err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US); - AutoReleaseMediaBuffer a(audioBuffer, mDecoder.get()); - - switch (err) { - case OK: - { - nsresult rv = CreateAudioData(audioBuffer, aStreamOffset); - NS_ENSURE_SUCCESS(rv, rv); - break; - } - case android::INFO_FORMAT_CHANGED: - { - // If the format changed, update our cached info. - GADM_LOG("Decoder format changed"); - sp<AMessage> audioCodecFormat; - - if (mDecoder->getOutputFormat(&audioCodecFormat) != OK || - audioCodecFormat == nullptr) { - return NS_ERROR_UNEXPECTED; - } - - int32_t codec_channel_count = 0; - int32_t codec_sample_rate = 0; - - if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) || - !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) { - return NS_ERROR_UNEXPECTED; - } - - // Update AudioInfo - AudioConfig::ChannelLayout layout(codec_channel_count); - if (!layout.IsValid()) { - return NS_ERROR_FAILURE; - } - mAudioChannels = codec_channel_count; - mAudioRate = codec_sample_rate; - - return Output(aStreamOffset, aOutData); - } - case android::INFO_OUTPUT_BUFFERS_CHANGED: - { - GADM_LOG("Info Output Buffers Changed"); - if (mDecoder->UpdateOutputBuffers()) { - return Output(aStreamOffset, aOutData); - } - return NS_ERROR_FAILURE; - } - case -EAGAIN: - { - return NS_ERROR_NOT_AVAILABLE; - } - case android::ERROR_END_OF_STREAM: - { - GADM_LOG("Got EOS frame!"); - nsresult rv = CreateAudioData(audioBuffer, aStreamOffset); - NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); - MOZ_ASSERT(mAudioQueue.GetSize() > 0); - mAudioQueue.Finish(); - break; - } - case -ETIMEDOUT: - { - GADM_LOG("Timeout. can try again next time"); - return NS_ERROR_UNEXPECTED; - } - default: - { - GADM_LOG("Decoder failed, err=%d", err); - return NS_ERROR_UNEXPECTED; - } - } - - if (mAudioQueue.GetSize() > 0) { - aOutData = mAudioQueue.PopFront(); - // Return NS_ERROR_ABORT at the last sample. - return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK; - } - - return NS_ERROR_NOT_AVAILABLE; -} - -void -GonkAudioDecoderManager::ProcessFlush() -{ - GADM_LOG("FLUSH<<<"); - mAudioQueue.Reset(); - GADM_LOG(">>>FLUSH"); - GonkDecoderManager::ProcessFlush(); -} - -void -GonkAudioDecoderManager::ResetEOS() -{ - GADM_LOG("ResetEOS(<<<"); - mAudioQueue.Reset(); - GADM_LOG(">>>ResetEOS("); - GonkDecoderManager::ResetEOS(); -} - -} // namespace mozilla diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.h b/dom/media/platforms/gonk/GonkAudioDecoderManager.h deleted file mode 100644 index aa35d620e..000000000 --- a/dom/media/platforms/gonk/GonkAudioDecoderManager.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 !defined(GonkAudioDecoderManager_h_) -#define GonkAudioDecoderManager_h_ - -#include "AudioCompactor.h" -#include "mozilla/RefPtr.h" -#include "GonkMediaDataDecoder.h" - -using namespace android; - -namespace android { -class MOZ_EXPORT MediaBuffer; -} // namespace android - -namespace mozilla { - -class GonkAudioDecoderManager : public GonkDecoderManager { -typedef android::MediaCodecProxy MediaCodecProxy; -public: - GonkAudioDecoderManager(const AudioInfo& aConfig); - - virtual ~GonkAudioDecoderManager(); - - RefPtr<InitPromise> Init() override; - - nsresult Output(int64_t aStreamOffset, - RefPtr<MediaData>& aOutput) override; - - void ProcessFlush() override; - virtual void ResetEOS() override; - - const char* GetDescriptionName() const override - { - return "gonk audio decoder"; - } - -private: - bool InitMediaCodecProxy(); - - nsresult CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset); - - uint32_t mAudioChannels; - uint32_t mAudioRate; - const uint32_t mAudioProfile; - - MediaQueue<AudioData> mAudioQueue; - - AudioCompactor mAudioCompactor; - -}; - -} // namespace mozilla - -#endif // GonkAudioDecoderManager_h_ diff --git a/dom/media/platforms/gonk/GonkDecoderModule.cpp b/dom/media/platforms/gonk/GonkDecoderModule.cpp deleted file mode 100644 index 537bc299c..000000000 --- a/dom/media/platforms/gonk/GonkDecoderModule.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "GonkDecoderModule.h" -#include "GonkVideoDecoderManager.h" -#include "GonkAudioDecoderManager.h" -#include "mozilla/DebugOnly.h" -#include "GonkMediaDataDecoder.h" - -namespace mozilla { -GonkDecoderModule::GonkDecoderModule() -{ -} - -GonkDecoderModule::~GonkDecoderModule() -{ -} - -already_AddRefed<MediaDataDecoder> -GonkDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) -{ - RefPtr<MediaDataDecoder> decoder = - new GonkMediaDataDecoder(new GonkVideoDecoderManager(aParams.mImageContainer, aParams.VideoConfig()), - aParams.mCallback); - return decoder.forget(); -} - -already_AddRefed<MediaDataDecoder> -GonkDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams) -{ - RefPtr<MediaDataDecoder> decoder = - new GonkMediaDataDecoder(new GonkAudioDecoderManager(aParams.AudioConfig()), - aParams.mCallback); - return decoder.forget(); -} - -PlatformDecoderModule::ConversionRequired -GonkDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const -{ - if (aConfig.IsVideo()) { - return ConversionRequired::kNeedAnnexB; - } else { - return ConversionRequired::kNeedNone; - } -} - -bool -GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const -{ - return aMimeType.EqualsLiteral("audio/mp4a-latm") || - aMimeType.EqualsLiteral("audio/3gpp") || - aMimeType.EqualsLiteral("audio/amr-wb") || - aMimeType.EqualsLiteral("audio/mpeg") || - aMimeType.EqualsLiteral("video/mp4") || - aMimeType.EqualsLiteral("video/mp4v-es") || - aMimeType.EqualsLiteral("video/avc") || - aMimeType.EqualsLiteral("video/3gpp"); -} - -} // namespace mozilla diff --git a/dom/media/platforms/gonk/GonkDecoderModule.h b/dom/media/platforms/gonk/GonkDecoderModule.h deleted file mode 100644 index 4f29f0e75..000000000 --- a/dom/media/platforms/gonk/GonkDecoderModule.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 !defined(GonkPlatformDecoderModule_h_) -#define GonkPlatformDecoderModule_h_ - -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class GonkDecoderModule : public PlatformDecoderModule { -public: - GonkDecoderModule(); - virtual ~GonkDecoderModule(); - - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateVideoDecoder(const CreateDecoderParams& aParams) override; - - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateAudioDecoder(const CreateDecoderParams& aParams) override; - - ConversionRequired - DecoderNeedsConversion(const TrackInfo& aConfig) const override; - - bool SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const override; - -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp b/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp deleted file mode 100644 index 6d59d72e1..000000000 --- a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "GonkMediaDataDecoder.h" -#include "VideoUtils.h" -#include "nsTArray.h" -#include "MediaCodecProxy.h" - -#include <stagefright/foundation/ADebug.h> - -#include "mozilla/Logging.h" -#include <android/log.h> -#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__) -#define INPUT_TIMEOUT_US 0LL // Don't wait for buffer if none is available. -#define MIN_QUEUED_SAMPLES 2 - -#ifdef DEBUG -#include <utils/AndroidThreads.h> -#endif - -#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) - -using namespace android; - -namespace mozilla { - -bool -GonkDecoderManager::InitLoopers(MediaData::Type aType) -{ - MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr); - MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA); - - const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio"); - mDecodeLooper = new ALooper; - android::AString name("MediaCodecProxy/"); - name.append(suffix); - mDecodeLooper->setName(name.c_str()); - - mTaskLooper = new ALooper; - name.setTo("GonkDecoderManager/"); - name.append(suffix); - mTaskLooper->setName(name.c_str()); - mTaskLooper->registerHandler(this); - -#ifdef DEBUG - sp<AMessage> findThreadId(new AMessage(kNotifyFindLooperId, id())); - findThreadId->post(); -#endif - - return mDecodeLooper->start() == OK && mTaskLooper->start() == OK; -} - -nsresult -GonkDecoderManager::Input(MediaRawData* aSample) -{ - RefPtr<MediaRawData> sample; - - if (aSample) { - sample = aSample; - } else { - // It means EOS with empty sample. - sample = new MediaRawData(); - } - { - MutexAutoLock lock(mMutex); - mQueuedSamples.AppendElement(sample); - } - - sp<AMessage> input = new AMessage(kNotifyProcessInput, id()); - if (!aSample) { - input->setInt32("input-eos", 1); - } - input->post(); - return NS_OK; -} - -int32_t -GonkDecoderManager::ProcessQueuedSamples() -{ - MOZ_ASSERT(OnTaskLooper()); - - MutexAutoLock lock(mMutex); - status_t rv; - while (mQueuedSamples.Length()) { - RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0); - rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()), - data->Size(), - data->mTime, - 0, - INPUT_TIMEOUT_US); - if (rv == OK) { - mQueuedSamples.RemoveElementAt(0); - mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime, - /* eos */ data->Data() == nullptr)); - } else if (rv == -EAGAIN || rv == -ETIMEDOUT) { - // In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill - // buffer on time. - break; - } else { - return rv; - } - } - return mQueuedSamples.Length(); -} - -nsresult -GonkDecoderManager::Flush() -{ - if (mDecoder == nullptr) { - GMDD_LOG("Decoder is not initialized"); - return NS_ERROR_UNEXPECTED; - } - - if (!mInitPromise.IsEmpty()) { - return NS_OK; - } - - { - MutexAutoLock lock(mMutex); - mQueuedSamples.Clear(); - } - - MonitorAutoLock lock(mFlushMonitor); - mIsFlushing = true; - sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id()); - flush->post(); - while (mIsFlushing) { - lock.Wait(); - } - return NS_OK; -} - -nsresult -GonkDecoderManager::Shutdown() -{ - if (mDecoder.get()) { - mDecoder->stop(); - mDecoder->ReleaseMediaResources(); - mDecoder = nullptr; - } - - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); - - return NS_OK; -} - -size_t -GonkDecoderManager::NumQueuedSamples() -{ - MutexAutoLock lock(mMutex); - return mQueuedSamples.Length(); -} - -void -GonkDecoderManager::ProcessInput(bool aEndOfStream) -{ - MOZ_ASSERT(OnTaskLooper()); - - status_t rv = ProcessQueuedSamples(); - if (rv >= 0) { - if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) { - mDecodeCallback->InputExhausted(); - } - - if (mToDo.get() == nullptr) { - mToDo = new AMessage(kNotifyDecoderActivity, id()); - if (aEndOfStream) { - mToDo->setInt32("input-eos", 1); - } - mDecoder->requestActivityNotification(mToDo); - } else if (aEndOfStream) { - mToDo->setInt32("input-eos", 1); - } - } else { - GMDD_LOG("input processed: error#%d", rv); - mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - __func__)); - } -} - -void -GonkDecoderManager::ProcessFlush() -{ - MOZ_ASSERT(OnTaskLooper()); - - mLastTime = INT64_MIN; - MonitorAutoLock lock(mFlushMonitor); - mWaitOutput.Clear(); - if (mDecoder->flush() != OK) { - GMDD_LOG("flush error"); - mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - __func__)); - } - mIsFlushing = false; - lock.NotifyAll(); -} - -// Use output timestamp to determine which output buffer is already returned -// and remove corresponding info, except for EOS, from the waiting list. -// This method handles the cases that audio decoder sends multiple output -// buffers for one input. -void -GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo) -{ - MOZ_ASSERT(OnTaskLooper()); - - size_t i; - for (i = 0; i < mWaitOutput.Length(); i++) { - const auto& item = mWaitOutput.ElementAt(i); - if (item.mEOS || item.mTimestamp > aForgetUpTo) { - break; - } - } - if (i > 0) { - mWaitOutput.RemoveElementsAt(0, i); - } -} - -void -GonkDecoderManager::ProcessToDo(bool aEndOfStream) -{ - MOZ_ASSERT(OnTaskLooper()); - - MOZ_ASSERT(mToDo.get() != nullptr); - mToDo.clear(); - - if (NumQueuedSamples() > 0 && ProcessQueuedSamples() < 0) { - mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - __func__)); - return; - } - - while (mWaitOutput.Length() > 0) { - RefPtr<MediaData> output; - WaitOutputInfo wait = mWaitOutput.ElementAt(0); - nsresult rv = Output(wait.mOffset, output); - if (rv == NS_OK) { - MOZ_ASSERT(output); - mDecodeCallback->Output(output); - UpdateWaitingList(output->mTime); - } else if (rv == NS_ERROR_ABORT) { - // EOS - MOZ_ASSERT(mQueuedSamples.IsEmpty()); - if (output) { - mDecodeCallback->Output(output); - UpdateWaitingList(output->mTime); - } - MOZ_ASSERT(mWaitOutput.Length() == 1); - mWaitOutput.RemoveElementAt(0); - mDecodeCallback->DrainComplete(); - ResetEOS(); - return; - } else if (rv == NS_ERROR_NOT_AVAILABLE) { - break; - } else { - mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - __func__)); - return; - } - } - - if (!aEndOfStream && NumQueuedSamples() <= MIN_QUEUED_SAMPLES) { - mDecodeCallback->InputExhausted(); - // No need to shedule todo task this time because InputExhausted() will - // cause Input() to be invoked and do it for us. - return; - } - - if (NumQueuedSamples() || mWaitOutput.Length() > 0) { - mToDo = new AMessage(kNotifyDecoderActivity, id()); - if (aEndOfStream) { - mToDo->setInt32("input-eos", 1); - } - mDecoder->requestActivityNotification(mToDo); - } -} - -void -GonkDecoderManager::ResetEOS() -{ - // After eos, android::MediaCodec needs to be flushed to receive next input - mWaitOutput.Clear(); - if (mDecoder->flush() != OK) { - GMDD_LOG("flush error"); - mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - __func__)); - } -} - -void -GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage) -{ - switch (aMessage->what()) { - case kNotifyProcessInput: - { - int32_t eos = 0; - ProcessInput(aMessage->findInt32("input-eos", &eos) && eos); - break; - } - case kNotifyProcessFlush: - { - ProcessFlush(); - break; - } - case kNotifyDecoderActivity: - { - int32_t eos = 0; - ProcessToDo(aMessage->findInt32("input-eos", &eos) && eos); - break; - } -#ifdef DEBUG - case kNotifyFindLooperId: - { - mTaskLooperId = androidGetThreadId(); - MOZ_ASSERT(mTaskLooperId); - break; - } -#endif - default: - { - TRESPASS(); - break; - } - } -} - -#ifdef DEBUG -bool -GonkDecoderManager::OnTaskLooper() -{ - return androidGetThreadId() == mTaskLooperId; -} -#endif - -GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager, - MediaDataDecoderCallback* aCallback) - : mManager(aManager) -{ - MOZ_COUNT_CTOR(GonkMediaDataDecoder); - mManager->SetDecodeCallback(aCallback); -} - -GonkMediaDataDecoder::~GonkMediaDataDecoder() -{ - MOZ_COUNT_DTOR(GonkMediaDataDecoder); -} - -RefPtr<MediaDataDecoder::InitPromise> -GonkMediaDataDecoder::Init() -{ - return mManager->Init(); -} - -void -GonkMediaDataDecoder::Shutdown() -{ - mManager->Shutdown(); - - // Because codec allocated runnable and init promise is at reader TaskQueue, - // so manager needs to be destroyed at reader TaskQueue to prevent racing. - mManager = nullptr; -} - -// Inserts data into the decoder's pipeline. -void -GonkMediaDataDecoder::Input(MediaRawData* aSample) -{ - mManager->Input(aSample); -} - -void -GonkMediaDataDecoder::Flush() -{ - mManager->Flush(); -} - -void -GonkMediaDataDecoder::Drain() -{ - mManager->Input(nullptr); -} - -} // namespace mozilla diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.h b/dom/media/platforms/gonk/GonkMediaDataDecoder.h deleted file mode 100644 index bba2a8645..000000000 --- a/dom/media/platforms/gonk/GonkMediaDataDecoder.h +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 !defined(GonkMediaDataDecoder_h_) -#define GonkMediaDataDecoder_h_ -#include "PlatformDecoderModule.h" -#include <stagefright/foundation/AHandler.h> - -namespace android { -struct ALooper; -class MediaBuffer; -class MediaCodecProxy; -} // namespace android - -namespace mozilla { -class MediaRawData; - -// Manage the data flow from inputting encoded data and outputting decode data. -class GonkDecoderManager : public android::AHandler { -public: - typedef TrackInfo::TrackType TrackType; - typedef MediaDataDecoder::InitPromise InitPromise; - - virtual ~GonkDecoderManager() {} - - virtual RefPtr<InitPromise> Init() = 0; - virtual const char* GetDescriptionName() const = 0; - - // Asynchronously send sample into mDecoder. If out of input buffer, aSample - // will be queued for later re-send. - nsresult Input(MediaRawData* aSample); - - // Flush the queued samples and signal decoder to throw all pending input/output away. - nsresult Flush(); - - // Shutdown decoder and rejects the init promise. - virtual nsresult Shutdown(); - - // How many samples are waiting for processing. - size_t NumQueuedSamples(); - - // Set callback for decoder events, such as requesting more input, - // returning output, or reporting error. - void SetDecodeCallback(MediaDataDecoderCallback* aCallback) - { - mDecodeCallback = aCallback; - } - -protected: - GonkDecoderManager() - : mMutex("GonkDecoderManager") - , mLastTime(INT64_MIN) - , mFlushMonitor("GonkDecoderManager::Flush") - , mIsFlushing(false) - , mDecodeCallback(nullptr) - {} - - bool InitLoopers(MediaData::Type aType); - - void onMessageReceived(const android::sp<android::AMessage> &aMessage) override; - - // Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE - // when output is not produced yet. - // If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error - // will be reported through mDecodeCallback. - virtual nsresult Output(int64_t aStreamOffset, - RefPtr<MediaData>& aOutput) = 0; - - // Send queued samples to OMX. It returns how many samples are still in - // queue after processing, or negative error code if failed. - int32_t ProcessQueuedSamples(); - - void ProcessInput(bool aEndOfStream); - virtual void ProcessFlush(); - void ProcessToDo(bool aEndOfStream); - virtual void ResetEOS(); - - RefPtr<MediaByteBuffer> mCodecSpecificData; - - nsAutoCString mMimeType; - - // MediaCodedc's wrapper that performs the decoding. - android::sp<android::MediaCodecProxy> mDecoder; - // Looper for mDecoder to run on. - android::sp<android::ALooper> mDecodeLooper; - // Looper to run decode tasks such as processing input, output, flush, and - // recycling output buffers. - android::sp<android::ALooper> mTaskLooper; - // Message codes for tasks running on mTaskLooper. - enum { - // Decoder will send this to indicate internal state change such as input or - // output buffers availability. Used to run pending input & output tasks. - kNotifyDecoderActivity = 'nda ', - // Signal the decoder to flush. - kNotifyProcessFlush = 'npf ', - // Used to process queued samples when there is new input. - kNotifyProcessInput = 'npi ', -#ifdef DEBUG - kNotifyFindLooperId = 'nfli', -#endif - }; - - MozPromiseHolder<InitPromise> mInitPromise; - - Mutex mMutex; // Protects mQueuedSamples. - // A queue that stores the samples waiting to be sent to mDecoder. - // Empty element means EOS and there shouldn't be any sample be queued after it. - // Samples are queued in caller's thread and dequeued in mTaskLooper. - nsTArray<RefPtr<MediaRawData>> mQueuedSamples; - - // The last decoded frame presentation time. Only accessed on mTaskLooper. - int64_t mLastTime; - - Monitor mFlushMonitor; // Waits for flushing to complete. - bool mIsFlushing; // Protected by mFlushMonitor. - - // Remembers the notification that is currently waiting for the decoder event - // to avoid requesting more than one notification at the time, which is - // forbidden by mDecoder. - android::sp<android::AMessage> mToDo; - - // Stores sample info for output buffer processing later. - struct WaitOutputInfo { - WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS) - : mOffset(aOffset) - , mTimestamp(aTimestamp) - , mEOS(aEOS) - {} - const int64_t mOffset; - const int64_t mTimestamp; - const bool mEOS; - }; - - nsTArray<WaitOutputInfo> mWaitOutput; - - MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error. - -private: - void UpdateWaitingList(int64_t aForgetUpTo); - -#ifdef DEBUG - typedef void* LooperId; - - bool OnTaskLooper(); - LooperId mTaskLooperId; -#endif -}; - -class AutoReleaseMediaBuffer -{ -public: - AutoReleaseMediaBuffer(android::MediaBuffer* aBuffer, android::MediaCodecProxy* aCodec) - : mBuffer(aBuffer) - , mCodec(aCodec) - {} - - ~AutoReleaseMediaBuffer() - { - MOZ_ASSERT(mCodec.get()); - if (mBuffer) { - mCodec->ReleaseMediaBuffer(mBuffer); - } - } - - android::MediaBuffer* forget() - { - android::MediaBuffer* tmp = mBuffer; - mBuffer = nullptr; - return tmp; - } - -private: - android::MediaBuffer* mBuffer; - android::sp<android::MediaCodecProxy> mCodec; -}; - -// Samples are decoded using the GonkDecoder (MediaCodec) -// created by the GonkDecoderManager. This class implements -// the higher-level logic that drives mapping the Gonk to the async -// MediaDataDecoder interface. The specifics of decoding the exact stream -// type are handled by GonkDecoderManager and the GonkDecoder it creates. -class GonkMediaDataDecoder : public MediaDataDecoder { -public: - GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager, - MediaDataDecoderCallback* aCallback); - - ~GonkMediaDataDecoder(); - - RefPtr<InitPromise> Init() override; - - void Input(MediaRawData* aSample) override; - - void Flush() override; - - void Drain() override; - - void Shutdown() override; - - const char* GetDescriptionName() const override - { - return "gonk decoder"; - } - -private: - - android::sp<GonkDecoderManager> mManager; -}; - -} // namespace mozilla - -#endif // GonkMediaDataDecoder_h_ diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp deleted file mode 100644 index 0c7b3b6af..000000000 --- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp +++ /dev/null @@ -1,772 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "MediaCodecProxy.h" -#include <OMX_IVCommon.h> -#include <gui/Surface.h> -#include <ICrypto.h> -#include "GonkVideoDecoderManager.h" -#include "GrallocImages.h" -#include "MediaDecoderReader.h" -#include "ImageContainer.h" -#include "VideoUtils.h" -#include "nsThreadUtils.h" -#include "Layers.h" -#include "mozilla/Logging.h" -#include <stagefright/MediaBuffer.h> -#include <stagefright/MetaData.h> -#include <stagefright/MediaErrors.h> -#include <stagefright/foundation/AString.h> -#include "GonkNativeWindow.h" -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layers/TextureClient.h" -#include "mozilla/layers/TextureClientRecycleAllocator.h" -#include <cutils/properties.h> - -#define CODECCONFIG_TIMEOUT_US 10000LL -#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL - -#include <android/log.h> -#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__) - -#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) -using namespace mozilla::layers; -using namespace android; -typedef android::MediaCodecProxy MediaCodecProxy; - -namespace mozilla { - -class GonkTextureClientAllocationHelper : public layers::ITextureClientAllocationHelper -{ -public: - GonkTextureClientAllocationHelper(uint32_t aGrallocFormat, - gfx::IntSize aSize) - : ITextureClientAllocationHelper(gfx::SurfaceFormat::UNKNOWN, - aSize, - BackendSelector::Content, - TextureFlags::DEALLOCATE_CLIENT, - ALLOC_DISALLOW_BUFFERTEXTURECLIENT) - , mGrallocFormat(aGrallocFormat) - {} - - already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override - { - uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN | - android::GraphicBuffer::USAGE_SW_WRITE_OFTEN | - android::GraphicBuffer::USAGE_HW_TEXTURE; - - GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat, - gfx::BackendType::NONE, - usage, aAllocator->GetTextureForwarder()); - if (!texData) { - return nullptr; - } - sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer(); - if (!graphicBuffer.get()) { - return nullptr; - } - RefPtr<TextureClient> textureClient = - TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator->GetTextureForwarder()); - return textureClient.forget(); - } - - bool IsCompatible(TextureClient* aTextureClient) override - { - if (!aTextureClient) { - return false; - } - sp<GraphicBuffer> graphicBuffer = - static_cast<GrallocTextureData*>(aTextureClient->GetInternalData())->GetGraphicBuffer(); - if (!graphicBuffer.get() || - static_cast<uint32_t>(graphicBuffer->getPixelFormat()) != mGrallocFormat || - aTextureClient->GetSize() != mSize) { - return false; - } - return true; - } - -private: - uint32_t mGrallocFormat; -}; - -GonkVideoDecoderManager::GonkVideoDecoderManager( - mozilla::layers::ImageContainer* aImageContainer, - const VideoInfo& aConfig) - : mConfig(aConfig) - , mImageContainer(aImageContainer) - , mColorConverterBufferSize(0) - , mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock") - , mNeedsCopyBuffer(false) -{ - MOZ_COUNT_CTOR(GonkVideoDecoderManager); -} - -GonkVideoDecoderManager::~GonkVideoDecoderManager() -{ - MOZ_COUNT_DTOR(GonkVideoDecoderManager); -} - -nsresult -GonkVideoDecoderManager::Shutdown() -{ - mVideoCodecRequest.DisconnectIfExists(); - return GonkDecoderManager::Shutdown(); -} - -RefPtr<MediaDataDecoder::InitPromise> -GonkVideoDecoderManager::Init() -{ - mNeedsCopyBuffer = false; - - uint32_t maxWidth, maxHeight; - char propValue[PROPERTY_VALUE_MAX]; - property_get("ro.moz.omx.hw.max_width", propValue, "-1"); - maxWidth = -1 == atoi(propValue) ? MAX_VIDEO_WIDTH : atoi(propValue); - property_get("ro.moz.omx.hw.max_height", propValue, "-1"); - maxHeight = -1 == atoi(propValue) ? MAX_VIDEO_HEIGHT : atoi(propValue) ; - - if (uint32_t(mConfig.mImage.width * mConfig.mImage.height) > maxWidth * maxHeight) { - GVDM_LOG("Video resolution exceeds hw codec capability"); - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - // Validate the container-reported frame and pictureRect sizes. This ensures - // that our video frame creation code doesn't overflow. - if (!IsValidVideoRegion(mConfig.mImage, mConfig.ImageRect(), mConfig.mDisplay)) { - GVDM_LOG("It is not a valid region"); - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue(); - MOZ_ASSERT(mReaderTaskQueue); - - if (mDecodeLooper.get() != nullptr) { - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - if (!InitLoopers(MediaData::VIDEO_DATA)) { - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - RefPtr<InitPromise> p = mInitPromise.Ensure(__func__); - android::sp<GonkVideoDecoderManager> self = this; - mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, - mConfig.mMimeType.get(), - false); - - uint32_t capability = MediaCodecProxy::kEmptyCapability; - if (mDecoder->getCapability(&capability) == OK && (capability & - MediaCodecProxy::kCanExposeGraphicBuffer)) { -#if ANDROID_VERSION >= 21 - sp<IGonkGraphicBufferConsumer> consumer; - GonkBufferQueue::createBufferQueue(&mGraphicBufferProducer, &consumer); - mNativeWindow = new GonkNativeWindow(consumer); -#else - mNativeWindow = new GonkNativeWindow(); -#endif - } - - mVideoCodecRequest.Begin(mDecoder->AsyncAllocateVideoMediaCodec() - ->Then(mReaderTaskQueue, __func__, - [self] (bool) -> void { - self->mVideoCodecRequest.Complete(); - self->codecReserved(); - }, [self] (bool) -> void { - self->mVideoCodecRequest.Complete(); - self->codecCanceled(); - })); - - return p; -} - -nsresult -GonkVideoDecoderManager::CreateVideoData(MediaBuffer* aBuffer, - int64_t aStreamOffset, - VideoData **v) -{ - *v = nullptr; - RefPtr<VideoData> data; - int64_t timeUs; - int32_t keyFrame; - - if (aBuffer == nullptr) { - GVDM_LOG("Video Buffer is not valid!"); - return NS_ERROR_UNEXPECTED; - } - - AutoReleaseMediaBuffer autoRelease(aBuffer, mDecoder.get()); - - if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - GVDM_LOG("Decoder did not return frame time"); - return NS_ERROR_UNEXPECTED; - } - - if (mLastTime > timeUs) { - GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs); - return NS_ERROR_NOT_AVAILABLE; - } - mLastTime = timeUs; - - if (aBuffer->range_length() == 0) { - // Some decoders may return spurious empty buffers that we just want to ignore - // quoted from Android's AwesomePlayer.cpp - return NS_ERROR_NOT_AVAILABLE; - } - - if (!aBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) { - keyFrame = 0; - } - - gfx::IntRect picture = - mConfig.ScaledImageRect(mFrameInfo.mWidth, mFrameInfo.mHeight); - if (aBuffer->graphicBuffer().get()) { - data = CreateVideoDataFromGraphicBuffer(aBuffer, picture); - if (data && !mNeedsCopyBuffer) { - // RecycleCallback() will be responsible for release the buffer. - autoRelease.forget(); - } - mNeedsCopyBuffer = false; - } else { - data = CreateVideoDataFromDataBuffer(aBuffer, picture); - } - - if (!data) { - return NS_ERROR_UNEXPECTED; - } - // Fill necessary info. - data->mOffset = aStreamOffset; - data->mTime = timeUs; - data->mKeyframe = keyFrame; - - data.forget(v); - return NS_OK; -} - -// Copy pixels from one planar YUV to another. -static void -CopyYUV(PlanarYCbCrData& aSource, PlanarYCbCrData& aDestination) -{ - // Fill Y plane. - uint8_t* srcY = aSource.mYChannel; - gfx::IntSize ySize = aSource.mYSize; - uint8_t* destY = aDestination.mYChannel; - // Y plane. - for (int i = 0; i < ySize.height; i++) { - memcpy(destY, srcY, ySize.width); - srcY += aSource.mYStride; - destY += aDestination.mYStride; - } - - // Fill UV plane. - // Line start - uint8_t* srcU = aSource.mCbChannel; - uint8_t* srcV = aSource.mCrChannel; - uint8_t* destU = aDestination.mCbChannel; - uint8_t* destV = aDestination.mCrChannel; - - gfx::IntSize uvSize = aSource.mCbCrSize; - for (int i = 0; i < uvSize.height; i++) { - uint8_t* su = srcU; - uint8_t* sv = srcV; - uint8_t* du = destU; - uint8_t* dv =destV; - for (int j = 0; j < uvSize.width; j++) { - *du++ = *su++; - *dv++ = *sv++; - // Move to next pixel. - su += aSource.mCbSkip; - sv += aSource.mCrSkip; - du += aDestination.mCbSkip; - dv += aDestination.mCrSkip; - } - // Move to next line. - srcU += aSource.mCbCrStride; - srcV += aSource.mCbCrStride; - destU += aDestination.mCbCrStride; - destV += aDestination.mCbCrStride; - } -} - -inline static int -Align(int aX, int aAlign) -{ - return (aX + aAlign - 1) & ~(aAlign - 1); -} - -// Venus formats are doucmented in kernel/include/media/msm_media_info.h: -// * Y_Stride : Width aligned to 128 -// * UV_Stride : Width aligned to 128 -// * Y_Scanlines: Height aligned to 32 -// * UV_Scanlines: Height/2 aligned to 16 -// * Total size = align((Y_Stride * Y_Scanlines -// * + UV_Stride * UV_Scanlines + 4096), 4096) -static void -CopyVenus(uint8_t* aSrc, uint8_t* aDest, uint32_t aWidth, uint32_t aHeight) -{ - size_t yStride = Align(aWidth, 128); - uint8_t* s = aSrc; - uint8_t* d = aDest; - for (size_t i = 0; i < aHeight; i++) { - memcpy(d, s, aWidth); - s += yStride; - d += yStride; - } - size_t uvStride = yStride; - size_t uvLines = (aHeight + 1) / 2; - size_t ySize = yStride * Align(aHeight, 32); - s = aSrc + ySize; - d = aDest + ySize; - for (size_t i = 0; i < uvLines; i++) { - memcpy(d, s, aWidth); - s += uvStride; - d += uvStride; - } -} - -static void -CopyGraphicBuffer(sp<GraphicBuffer>& aSource, sp<GraphicBuffer>& aDestination) -{ - void* srcPtr = nullptr; - aSource->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &srcPtr); - void* destPtr = nullptr; - aDestination->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destPtr); - MOZ_ASSERT(srcPtr && destPtr); - - // Build PlanarYCbCrData for source buffer. - PlanarYCbCrData srcData; - switch (aSource->getPixelFormat()) { - case HAL_PIXEL_FORMAT_YV12: { - // Android YV12 format is defined in system/core/include/system/graphics.h - srcData.mYChannel = static_cast<uint8_t*>(srcPtr); - srcData.mYSkip = 0; - srcData.mYSize.width = aSource->getWidth(); - srcData.mYSize.height = aSource->getHeight(); - srcData.mYStride = aSource->getStride(); - // 4:2:0. - srcData.mCbCrSize.width = srcData.mYSize.width / 2; - srcData.mCbCrSize.height = srcData.mYSize.height / 2; - srcData.mCrChannel = srcData.mYChannel + (srcData.mYStride * srcData.mYSize.height); - // Aligned to 16 bytes boundary. - srcData.mCbCrStride = Align(srcData.mYStride / 2, 16); - srcData.mCrSkip = 0; - srcData.mCbChannel = srcData.mCrChannel + (srcData.mCbCrStride * srcData.mCbCrSize.height); - srcData.mCbSkip = 0; - - // Build PlanarYCbCrData for destination buffer. - PlanarYCbCrData destData; - destData.mYChannel = static_cast<uint8_t*>(destPtr); - destData.mYSkip = 0; - destData.mYSize.width = aDestination->getWidth(); - destData.mYSize.height = aDestination->getHeight(); - destData.mYStride = aDestination->getStride(); - // 4:2:0. - destData.mCbCrSize.width = destData.mYSize.width / 2; - destData.mCbCrSize.height = destData.mYSize.height / 2; - destData.mCrChannel = destData.mYChannel + (destData.mYStride * destData.mYSize.height); - // Aligned to 16 bytes boundary. - destData.mCbCrStride = Align(destData.mYStride / 2, 16); - destData.mCrSkip = 0; - destData.mCbChannel = destData.mCrChannel + (destData.mCbCrStride * destData.mCbCrSize.height); - destData.mCbSkip = 0; - - CopyYUV(srcData, destData); - break; - } - case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: - CopyVenus(static_cast<uint8_t*>(srcPtr), - static_cast<uint8_t*>(destPtr), - aSource->getWidth(), - aSource->getHeight()); - break; - default: - NS_ERROR("Unsupported input gralloc image type. Should never be here."); - } - - - aSource->unlock(); - aDestination->unlock(); -} - -already_AddRefed<VideoData> -GonkVideoDecoderManager::CreateVideoDataFromGraphicBuffer(MediaBuffer* aSource, - gfx::IntRect& aPicture) -{ - sp<GraphicBuffer> srcBuffer(aSource->graphicBuffer()); - RefPtr<TextureClient> textureClient; - - if (mNeedsCopyBuffer) { - // Copy buffer contents for bug 1199809. - if (!mCopyAllocator) { - RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton(); - mCopyAllocator = new TextureClientRecycleAllocator(bridge); - } - if (!mCopyAllocator) { - GVDM_LOG("Create buffer allocator failed!"); - return nullptr; - } - - gfx::IntSize size(srcBuffer->getWidth(), srcBuffer->getHeight()); - GonkTextureClientAllocationHelper helper(srcBuffer->getPixelFormat(), size); - textureClient = mCopyAllocator->CreateOrRecycle(helper); - if (!textureClient) { - GVDM_LOG("Copy buffer allocation failed!"); - return nullptr; - } - - sp<GraphicBuffer> destBuffer = - static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer(); - - CopyGraphicBuffer(srcBuffer, destBuffer); - } else { - textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get()); - textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this); - static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource); - } - - RefPtr<VideoData> data = - VideoData::CreateAndCopyIntoTextureClient(mConfig, - 0, // Filled later by caller. - 0, // Filled later by caller. - 1, // No way to pass sample duration from muxer to - // OMX codec, so we hardcode the duration here. - textureClient, - false, // Filled later by caller. - -1, - aPicture); - return data.forget(); -} - -already_AddRefed<VideoData> -GonkVideoDecoderManager::CreateVideoDataFromDataBuffer(MediaBuffer* aSource, gfx::IntRect& aPicture) -{ - if (!aSource->data()) { - GVDM_LOG("No data in Video Buffer!"); - return nullptr; - } - uint8_t *yuv420p_buffer = (uint8_t *)aSource->data(); - int32_t stride = mFrameInfo.mStride; - int32_t slice_height = mFrameInfo.mSliceHeight; - - // Converts to OMX_COLOR_FormatYUV420Planar - if (mFrameInfo.mColorFormat != OMX_COLOR_FormatYUV420Planar) { - ARect crop; - crop.top = 0; - crop.bottom = mFrameInfo.mHeight; - crop.left = 0; - crop.right = mFrameInfo.mWidth; - yuv420p_buffer = GetColorConverterBuffer(mFrameInfo.mWidth, mFrameInfo.mHeight); - if (mColorConverter.convertDecoderOutputToI420(aSource->data(), - mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) { - GVDM_LOG("Color conversion failed!"); - return nullptr; - } - stride = mFrameInfo.mWidth; - slice_height = mFrameInfo.mHeight; - } - - size_t yuv420p_y_size = stride * slice_height; - size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2); - uint8_t *yuv420p_y = yuv420p_buffer; - uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size; - uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size; - - VideoData::YCbCrBuffer b; - b.mPlanes[0].mData = yuv420p_y; - b.mPlanes[0].mWidth = mFrameInfo.mWidth; - b.mPlanes[0].mHeight = mFrameInfo.mHeight; - b.mPlanes[0].mStride = stride; - b.mPlanes[0].mOffset = 0; - b.mPlanes[0].mSkip = 0; - - b.mPlanes[1].mData = yuv420p_u; - b.mPlanes[1].mWidth = (mFrameInfo.mWidth + 1) / 2; - b.mPlanes[1].mHeight = (mFrameInfo.mHeight + 1) / 2; - b.mPlanes[1].mStride = (stride + 1) / 2; - b.mPlanes[1].mOffset = 0; - b.mPlanes[1].mSkip = 0; - - b.mPlanes[2].mData = yuv420p_v; - b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2; - b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2; - b.mPlanes[2].mStride = (stride + 1) / 2; - b.mPlanes[2].mOffset = 0; - b.mPlanes[2].mSkip = 0; - - RefPtr<VideoData> data = - VideoData::CreateAndCopyData(mConfig, - mImageContainer, - 0, // Filled later by caller. - 0, // Filled later by caller. - 1, // We don't know the duration. - b, - 0, // Filled later by caller. - -1, - aPicture); - - return data.forget(); -} - -bool -GonkVideoDecoderManager::SetVideoFormat() -{ - // read video metadata from MediaCodec - sp<AMessage> codecFormat; - if (mDecoder->getOutputFormat(&codecFormat) == OK) { - AString mime; - int32_t width = 0; - int32_t height = 0; - int32_t stride = 0; - int32_t slice_height = 0; - int32_t color_format = 0; - int32_t crop_left = 0; - int32_t crop_top = 0; - int32_t crop_right = 0; - int32_t crop_bottom = 0; - if (!codecFormat->findString("mime", &mime) || - !codecFormat->findInt32("width", &width) || - !codecFormat->findInt32("height", &height) || - !codecFormat->findInt32("stride", &stride) || - !codecFormat->findInt32("slice-height", &slice_height) || - !codecFormat->findInt32("color-format", &color_format) || - !codecFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) { - GVDM_LOG("Failed to find values"); - return false; - } - mFrameInfo.mWidth = width; - mFrameInfo.mHeight = height; - mFrameInfo.mStride = stride; - mFrameInfo.mSliceHeight = slice_height; - mFrameInfo.mColorFormat = color_format; - - nsIntSize displaySize(width, height); - if (!IsValidVideoRegion(mConfig.mDisplay, - mConfig.ScaledImageRect(width, height), - displaySize)) { - GVDM_LOG("It is not a valid region"); - return false; - } - return true; - } - GVDM_LOG("Fail to get output format"); - return false; -} - -// Blocks until decoded sample is produced by the deoder. -nsresult -GonkVideoDecoderManager::Output(int64_t aStreamOffset, - RefPtr<MediaData>& aOutData) -{ - aOutData = nullptr; - status_t err; - if (mDecoder == nullptr) { - GVDM_LOG("Decoder is not inited"); - return NS_ERROR_UNEXPECTED; - } - MediaBuffer* outputBuffer = nullptr; - err = mDecoder->Output(&outputBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US); - - switch (err) { - case OK: - { - RefPtr<VideoData> data; - nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data)); - if (rv == NS_ERROR_NOT_AVAILABLE) { - // Decoder outputs a empty video buffer, try again - return NS_ERROR_NOT_AVAILABLE; - } else if (rv != NS_OK || data == nullptr) { - GVDM_LOG("Failed to create VideoData"); - return NS_ERROR_UNEXPECTED; - } - aOutData = data; - return NS_OK; - } - case android::INFO_FORMAT_CHANGED: - { - // If the format changed, update our cached info. - GVDM_LOG("Decoder format changed"); - if (!SetVideoFormat()) { - return NS_ERROR_UNEXPECTED; - } - return Output(aStreamOffset, aOutData); - } - case android::INFO_OUTPUT_BUFFERS_CHANGED: - { - if (mDecoder->UpdateOutputBuffers()) { - return Output(aStreamOffset, aOutData); - } - GVDM_LOG("Fails to update output buffers!"); - return NS_ERROR_FAILURE; - } - case -EAGAIN: - { -// GVDM_LOG("Need to try again!"); - return NS_ERROR_NOT_AVAILABLE; - } - case android::ERROR_END_OF_STREAM: - { - GVDM_LOG("Got the EOS frame!"); - RefPtr<VideoData> data; - nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data)); - if (rv == NS_ERROR_NOT_AVAILABLE) { - // For EOS, no need to do any thing. - return NS_ERROR_ABORT; - } - if (rv != NS_OK || data == nullptr) { - GVDM_LOG("Failed to create video data"); - return NS_ERROR_UNEXPECTED; - } - aOutData = data; - return NS_ERROR_ABORT; - } - case -ETIMEDOUT: - { - GVDM_LOG("Timeout. can try again next time"); - return NS_ERROR_UNEXPECTED; - } - default: - { - GVDM_LOG("Decoder failed, err=%d", err); - return NS_ERROR_UNEXPECTED; - } - } - - return NS_OK; -} - -void -GonkVideoDecoderManager::codecReserved() -{ - if (mInitPromise.IsEmpty()) { - return; - } - GVDM_LOG("codecReserved"); - sp<AMessage> format = new AMessage; - sp<Surface> surface; - status_t rv = OK; - // Fixed values - GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mConfig.mMimeType.get(), mConfig.mImage.width, mConfig.mImage.height); - format->setString("mime", mConfig.mMimeType.get()); - format->setInt32("width", mConfig.mImage.width); - format->setInt32("height", mConfig.mImage.height); - // Set the "moz-use-undequeued-bufs" to use the undeque buffers to accelerate - // the video decoding. - format->setInt32("moz-use-undequeued-bufs", 1); - if (mNativeWindow != nullptr) { -#if ANDROID_VERSION >= 21 - surface = new Surface(mGraphicBufferProducer); -#else - surface = new Surface(mNativeWindow->getBufferQueue()); -#endif - } - mDecoder->configure(format, surface, nullptr, 0); - mDecoder->Prepare(); - - if (mConfig.mMimeType.EqualsLiteral("video/mp4v-es")) { - rv = mDecoder->Input(mConfig.mCodecSpecificConfig->Elements(), - mConfig.mCodecSpecificConfig->Length(), 0, - android::MediaCodec::BUFFER_FLAG_CODECCONFIG, - CODECCONFIG_TIMEOUT_US); - } - - if (rv != OK) { - GVDM_LOG("Failed to configure codec!!!!"); - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - - mInitPromise.Resolve(TrackType::kVideoTrack, __func__); -} - -void -GonkVideoDecoderManager::codecCanceled() -{ - GVDM_LOG("codecCanceled"); - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); -} - -// Called on GonkDecoderManager::mTaskLooper thread. -void -GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage) -{ - switch (aMessage->what()) { - case kNotifyPostReleaseBuffer: - { - ReleaseAllPendingVideoBuffers(); - break; - } - - default: - { - GonkDecoderManager::onMessageReceived(aMessage); - break; - } - } -} - -uint8_t * -GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight) -{ - // Allocate a temporary YUV420Planer buffer. - size_t yuv420p_y_size = aWidth * aHeight; - size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2); - size_t yuv420p_v_size = yuv420p_u_size; - size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size; - if (mColorConverterBufferSize != yuv420p_size) { - mColorConverterBuffer = MakeUnique<uint8_t[]>(yuv420p_size); - mColorConverterBufferSize = yuv420p_size; - } - return mColorConverterBuffer.get(); -} - -/* static */ -void -GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure) -{ - MOZ_ASSERT(aClient && !aClient->IsDead()); - GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure); - GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData()); - aClient->ClearRecycleCallback(); - FenceHandle handle = aClient->GetAndResetReleaseFenceHandle(); - videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle); -} - -void GonkVideoDecoderManager::PostReleaseVideoBuffer( - android::MediaBuffer *aBuffer, - FenceHandle aReleaseFence) -{ - { - MutexAutoLock autoLock(mPendingReleaseItemsLock); - if (aBuffer) { - mPendingReleaseItems.AppendElement(ReleaseItem(aBuffer, aReleaseFence)); - } - } - sp<AMessage> notify = - new AMessage(kNotifyPostReleaseBuffer, id()); - notify->post(); - -} - -void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffers() -{ - nsTArray<ReleaseItem> releasingItems; - { - MutexAutoLock autoLock(mPendingReleaseItemsLock); - releasingItems.AppendElements(mPendingReleaseItems); - mPendingReleaseItems.Clear(); - } - - // Free all pending video buffers without holding mPendingReleaseItemsLock. - size_t size = releasingItems.Length(); - for (size_t i = 0; i < size; i++) { - RefPtr<FenceHandle::FdObj> fdObj = releasingItems[i].mReleaseFence.GetAndResetFdObj(); - sp<Fence> fence = new Fence(fdObj->GetAndResetFd()); - fence->waitForever("GonkVideoDecoderManager"); - mDecoder->ReleaseMediaBuffer(releasingItems[i].mBuffer); - } - releasingItems.Clear(); -} - -} // namespace mozilla diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.h b/dom/media/platforms/gonk/GonkVideoDecoderManager.h deleted file mode 100644 index 343bb2a5c..000000000 --- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 !defined(GonkVideoDecoderManager_h_) -#define GonkVideoDecoderManager_h_ - -#include "nsRect.h" -#include "GonkMediaDataDecoder.h" -#include "mozilla/RefPtr.h" -#include "I420ColorConverterHelper.h" -#include "MediaCodecProxy.h" -#include "GonkNativeWindow.h" -#include "mozilla/layers/FenceUtils.h" -#include "mozilla/UniquePtr.h" -#include <ui/Fence.h> - -using namespace android; - -namespace android { -class MediaBuffer; -struct MOZ_EXPORT AString; -class GonkNativeWindow; -} // namespace android - -namespace mozilla { - -namespace layers { -class TextureClient; -class TextureClientRecycleAllocator; -} // namespace mozilla::layers - -class GonkVideoDecoderManager : public GonkDecoderManager { -typedef android::MediaCodecProxy MediaCodecProxy; -typedef mozilla::layers::TextureClient TextureClient; - -public: - GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer, - const VideoInfo& aConfig); - - virtual ~GonkVideoDecoderManager(); - - RefPtr<InitPromise> Init() override; - - nsresult Output(int64_t aStreamOffset, - RefPtr<MediaData>& aOutput) override; - - nsresult Shutdown() override; - - const char* GetDescriptionName() const override - { - return "gonk video decoder"; - } - - static void RecycleCallback(TextureClient* aClient, void* aClosure); - -protected: - // Bug 1199809: workaround to avoid sending the graphic buffer by making a - // copy of output buffer after calling flush(). Bug 1203859 was created to - // reimplementing Gonk PDM on top of OpenMax IL directly. Its buffer - // management will work better with Gecko and solve problems like this. - void ProcessFlush() override - { - mNeedsCopyBuffer = true; - GonkDecoderManager::ProcessFlush(); - } - -private: - struct FrameInfo - { - int32_t mWidth = 0; - int32_t mHeight = 0; - int32_t mStride = 0; - int32_t mSliceHeight = 0; - int32_t mColorFormat = 0; - int32_t mCropLeft = 0; - int32_t mCropTop = 0; - int32_t mCropRight = 0; - int32_t mCropBottom = 0; - }; - - void onMessageReceived(const android::sp<android::AMessage> &aMessage) override; - - bool SetVideoFormat(); - - nsresult CreateVideoData(MediaBuffer* aBuffer, int64_t aStreamOffset, VideoData** aOutData); - already_AddRefed<VideoData> CreateVideoDataFromGraphicBuffer(android::MediaBuffer* aSource, - gfx::IntRect& aPicture); - already_AddRefed<VideoData> CreateVideoDataFromDataBuffer(android::MediaBuffer* aSource, - gfx::IntRect& aPicture); - - uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight); - - // For codec resource management - void codecReserved(); - void codecCanceled(); - - void ReleaseAllPendingVideoBuffers(); - void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer, - layers::FenceHandle mReleaseFence); - - VideoInfo mConfig; - - RefPtr<layers::ImageContainer> mImageContainer; - RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator; - - MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest; - FrameInfo mFrameInfo; - - // color converter - android::I420ColorConverterHelper mColorConverter; - UniquePtr<uint8_t[]> mColorConverterBuffer; - size_t mColorConverterBufferSize; - - android::sp<android::GonkNativeWindow> mNativeWindow; -#if ANDROID_VERSION >= 21 - android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer; -#endif - - enum { - kNotifyPostReleaseBuffer = 'nprb', - }; - - struct ReleaseItem { - ReleaseItem(android::MediaBuffer* aBuffer, layers::FenceHandle& aFence) - : mBuffer(aBuffer) - , mReleaseFence(aFence) {} - android::MediaBuffer* mBuffer; - layers::FenceHandle mReleaseFence; - }; - nsTArray<ReleaseItem> mPendingReleaseItems; - - // The lock protects mPendingReleaseItems. - Mutex mPendingReleaseItemsLock; - - // This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue(). - // It is for codec resource mangement, decoding task should not dispatch to it. - RefPtr<TaskQueue> mReaderTaskQueue; - - // Bug 1199809: do we need to make a copy of output buffer? Used only when - // the decoder outputs graphic buffers. - bool mNeedsCopyBuffer; -}; - -} // namespace mozilla - -#endif // GonkVideoDecoderManager_h_ diff --git a/dom/media/platforms/gonk/moz.build b/dom/media/platforms/gonk/moz.build deleted file mode 100644 index 014594977..000000000 --- a/dom/media/platforms/gonk/moz.build +++ /dev/null @@ -1,39 +0,0 @@ -# -*- 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/. - -EXPORTS += [ - 'GonkAudioDecoderManager.h', - 'GonkDecoderModule.h', - 'GonkMediaDataDecoder.h', - 'GonkVideoDecoderManager.h', -] -UNIFIED_SOURCES += [ - 'GonkAudioDecoderManager.cpp', - 'GonkDecoderModule.cpp', - 'GonkMediaDataDecoder.cpp', - 'GonkVideoDecoderManager.cpp', -] -LOCAL_INCLUDES += [ - '/dom/media/omx/', -] -include('/ipc/chromium/chromium-config.mozbuild') - -# Suppress some GCC/clang warnings being treated as errors: -# - about attributes on forward declarations for types that are already -# defined, which complains about an important MOZ_EXPORT for android::AString -# - about multi-character constants which are used in codec-related code -if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: - CXXFLAGS += [ - '-Wno-error=attributes', - '-Wno-error=multichar' - ] - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [ - 'frameworks/native/opengl/include',] -] diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build index 310820c91..3fb0cc842 100644 --- a/dom/media/platforms/moz.build +++ b/dom/media/platforms/moz.build @@ -70,10 +70,6 @@ if CONFIG['MOZ_APPLEMEDIA']: '-framework AudioToolbox', ] -if CONFIG['MOZ_GONK_MEDIACODEC']: - DEFINES['MOZ_GONK_MEDIACODEC'] = True - DIRS += ['gonk'] - include('/ipc/chromium/chromium-config.mozbuild') if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp b/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp deleted file mode 100644 index 870566cf5..000000000 --- a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 "GonkOmxPlatformLayer.h" - -#include <binder/MemoryDealer.h> -#include <cutils/properties.h> -#include <media/IOMX.h> -#include <media/stagefright/MediaCodecList.h> -#include <utils/List.h> - -#include "mozilla/Monitor.h" -#include "mozilla/layers/TextureClient.h" -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layers/TextureClientRecycleAllocator.h" - -#include "ImageContainer.h" -#include "MediaInfo.h" -#include "OmxDataDecoder.h" - - -#ifdef LOG -#undef LOG -#endif - -#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) - -#define CHECK_ERR(err) \ - if (err != OK) { \ - LOG("error %d at %s", err, __func__); \ - return NS_ERROR_FAILURE; \ - } \ - -// Android proprietary value. -#define ANDROID_OMX_VIDEO_CodingVP8 (static_cast<OMX_VIDEO_CODINGTYPE>(9)) - -using namespace android; - -namespace mozilla { - -// In Gonk, the software component name has prefix "OMX.google". It needs to -// have a way to use hardware codec first. -bool IsSoftwareCodec(const char* aComponentName) -{ - nsAutoCString str(aComponentName); - return (str.Find(NS_LITERAL_CSTRING("OMX.google.")) == -1 ? false : true); -} - -bool IsInEmulator() -{ - char propQemu[PROPERTY_VALUE_MAX]; - property_get("ro.kernel.qemu", propQemu, ""); - return !strncmp(propQemu, "1", 1); -} - -class GonkOmxObserver : public BnOMXObserver { -public: - void onMessage(const omx_message& aMsg) - { - switch (aMsg.type) { - case omx_message::EVENT: - { - sp<GonkOmxObserver> self = this; - nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () { - if (self->mClient && self->mClient->Event(aMsg.u.event_data.event, - aMsg.u.event_data.data1, - aMsg.u.event_data.data2)) - { - return; - } - }); - mTaskQueue->Dispatch(r.forget()); - break; - } - case omx_message::EMPTY_BUFFER_DONE: - { - sp<GonkOmxObserver> self = this; - nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () { - if (!self->mPromiseLayer) { - return; - } - BufferData::BufferID id = (BufferData::BufferID)aMsg.u.buffer_data.buffer; - self->mPromiseLayer->EmptyFillBufferDone(OMX_DirInput, id); - }); - mTaskQueue->Dispatch(r.forget()); - break; - } - case omx_message::FILL_BUFFER_DONE: - { - sp<GonkOmxObserver> self = this; - nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () { - if (!self->mPromiseLayer) { - return; - } - - // TODO: these codes look a little ugly, it'd be better to improve them. - RefPtr<BufferData> buf; - BufferData::BufferID id = (BufferData::BufferID)aMsg.u.extended_buffer_data.buffer; - buf = self->mPromiseLayer->FindAndRemoveBufferHolder(OMX_DirOutput, id); - MOZ_RELEASE_ASSERT(buf); - GonkBufferData* gonkBuffer = static_cast<GonkBufferData*>(buf.get()); - - // Copy the critical information to local buffer. - if (gonkBuffer->IsLocalBuffer()) { - gonkBuffer->mBuffer->nOffset = aMsg.u.extended_buffer_data.range_offset; - gonkBuffer->mBuffer->nFilledLen = aMsg.u.extended_buffer_data.range_length; - gonkBuffer->mBuffer->nFlags = aMsg.u.extended_buffer_data.flags; - gonkBuffer->mBuffer->nTimeStamp = aMsg.u.extended_buffer_data.timestamp; - } - self->mPromiseLayer->EmptyFillBufferDone(OMX_DirOutput, buf); - }); - mTaskQueue->Dispatch(r.forget()); - break; - } - default: - { - LOG("Unhandle event %d", aMsg.type); - } - } - } - - void Shutdown() - { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - mPromiseLayer = nullptr; - mClient = nullptr; - } - - GonkOmxObserver(TaskQueue* aTaskQueue, OmxPromiseLayer* aPromiseLayer, OmxDataDecoder* aDataDecoder) - : mTaskQueue(aTaskQueue) - , mPromiseLayer(aPromiseLayer) - , mClient(aDataDecoder) - {} - -protected: - RefPtr<TaskQueue> mTaskQueue; - // TODO: - // we should combine both event handlers into one. And we should provide - // an unified way for event handling in OmxPlatformLayer class. - RefPtr<OmxPromiseLayer> mPromiseLayer; - RefPtr<OmxDataDecoder> mClient; -}; - -// This class allocates Gralloc buffer and manages TextureClient's recycle. -class GonkTextureClientRecycleHandler : public layers::ITextureClientRecycleAllocator -{ - typedef MozPromise<layers::TextureClient*, nsresult, /* IsExclusive = */ true> TextureClientRecyclePromise; - -public: - GonkTextureClientRecycleHandler(OMX_VIDEO_PORTDEFINITIONTYPE& aDef) - : ITextureClientRecycleAllocator() - , mMonitor("GonkTextureClientRecycleHandler") - { - RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton(); - - // Allocate Gralloc texture memory. - layers::GrallocTextureData* textureData = - layers::GrallocTextureData::Create(gfx::IntSize(aDef.nFrameWidth, aDef.nFrameHeight), - aDef.eColorFormat, - gfx::BackendType::NONE, - GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN, - bridge); - - mGraphBuffer = textureData->GetGraphicBuffer(); - MOZ_ASSERT(mGraphBuffer.get()); - - mTextureClient = - layers::TextureClient::CreateWithData(textureData, - layers::TextureFlags::DEALLOCATE_CLIENT | layers::TextureFlags::RECYCLE, - bridge); - MOZ_ASSERT(mTextureClient); - - mPromise.SetMonitor(&mMonitor); - } - - RefPtr<TextureClientRecyclePromise> WaitforRecycle() - { - MonitorAutoLock lock(mMonitor); - MOZ_ASSERT(!!mGraphBuffer.get()); - - mTextureClient->SetRecycleAllocator(this); - return mPromise.Ensure(__func__); - } - - // DO NOT use smart pointer to receive TextureClient; otherwise it will - // distrupt the reference count. - layers::TextureClient* GetTextureClient() - { - return mTextureClient; - } - - GraphicBuffer* GetGraphicBuffer() - { - MonitorAutoLock lock(mMonitor); - return mGraphBuffer.get(); - } - - // This function is called from layers thread. - void RecycleTextureClient(layers::TextureClient* aClient) override - { - MOZ_ASSERT(mTextureClient == aClient); - - // Clearing the recycle allocator drops a reference, so make sure we stay alive - // for the duration of this function. - RefPtr<GonkTextureClientRecycleHandler> kungFuDeathGrip(this); - aClient->SetRecycleAllocator(nullptr); - - { - MonitorAutoLock lock(mMonitor); - mPromise.ResolveIfExists(mTextureClient, __func__); - } - } - - void Shutdown() - { - MonitorAutoLock lock(mMonitor); - - mPromise.RejectIfExists(NS_ERROR_FAILURE, __func__); - - // DO NOT clear TextureClient here. - // The ref count could be 1 and RecycleCallback will be called if we clear - // the ref count here. That breaks the whole mechanism. (RecycleCallback - // should be called from layers) - mGraphBuffer = nullptr; - } - -private: - // Because TextureClient calls RecycleCallbackl when ref count is 1, so we - // should hold only one reference here and use raw pointer when out of this - // class. - RefPtr<layers::TextureClient> mTextureClient; - - // It is protected by mMonitor. - sp<android::GraphicBuffer> mGraphBuffer; - - // It is protected by mMonitor. - MozPromiseHolder<TextureClientRecyclePromise> mPromise; - - Monitor mMonitor; -}; - -GonkBufferData::GonkBufferData(bool aLiveInLocal, - GonkOmxPlatformLayer* aGonkPlatformLayer) - : BufferData(nullptr) - , mId(0) - , mGonkPlatformLayer(aGonkPlatformLayer) -{ - if (!aLiveInLocal) { - mMirrorBuffer = new OMX_BUFFERHEADERTYPE; - PodZero(mMirrorBuffer.get()); - mBuffer = mMirrorBuffer.get(); - } -} - -void -GonkBufferData::ReleaseBuffer() -{ - if (mTextureClientRecycleHandler) { - mTextureClientRecycleHandler->Shutdown(); - mTextureClientRecycleHandler = nullptr; - } -} - -nsresult -GonkBufferData::InitSharedMemory(android::IMemory* aMemory) -{ - MOZ_RELEASE_ASSERT(mMirrorBuffer.get()); - - // aMemory is a IPC memory, it is safe to use it here. - mBuffer->pBuffer = (OMX_U8*)aMemory->pointer(); - mBuffer->nAllocLen = aMemory->size(); - return NS_OK; -} - -nsresult -GonkBufferData::InitLocalBuffer(IOMX::buffer_id aId) -{ - MOZ_RELEASE_ASSERT(!mMirrorBuffer.get()); - - mBuffer = (OMX_BUFFERHEADERTYPE*)aId; - return NS_OK; -} - -nsresult -GonkBufferData::InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef) -{ - mTextureClientRecycleHandler = new GonkTextureClientRecycleHandler(aDef); - - if (!mTextureClientRecycleHandler->GetGraphicBuffer()) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -already_AddRefed<MediaData> -GonkBufferData::GetPlatformMediaData() -{ - if (mGonkPlatformLayer->GetTrackInfo()->GetAsAudioInfo()) { - // This is audio decoding. - return nullptr; - } - - if (!mTextureClientRecycleHandler) { - // There is no GraphicBuffer, it should fallback to normal YUV420 VideoData. - return nullptr; - } - - VideoInfo info(*mGonkPlatformLayer->GetTrackInfo()->GetAsVideoInfo()); - RefPtr<VideoData> data = - VideoData::CreateAndCopyIntoTextureClient(info, - 0, - mBuffer->nTimeStamp, - 1, - mTextureClientRecycleHandler->GetTextureClient(), - false, - 0, - info.ImageRect()); - LOG("%p, disp width %d, height %d, pic width %d, height %d, time %ld", - this, info.mDisplay.width, info.mDisplay.height, - info.mImage.width, info.mImage.height, mBuffer->nTimeStamp); - - // Get TextureClient Promise here to wait for resolved. - RefPtr<GonkBufferData> self(this); - mTextureClientRecycleHandler->WaitforRecycle() - ->Then(mGonkPlatformLayer->GetTaskQueue(), __func__, - [self] () { - self->mPromise.ResolveIfExists(self, __func__); - }, - [self] () { - OmxBufferFailureHolder failure(OMX_ErrorUndefined, self); - self->mPromise.RejectIfExists(failure, __func__); - }); - - return data.forget(); -} - -GonkOmxPlatformLayer::GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder, - OmxPromiseLayer* aPromiseLayer, - TaskQueue* aTaskQueue, - layers::ImageContainer* aImageContainer) - : mTaskQueue(aTaskQueue) - , mImageContainer(aImageContainer) - , mNode(0) -{ - mOmxObserver = new GonkOmxObserver(mTaskQueue, aPromiseLayer, aDataDecoder); -} - -nsresult -GonkOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType, - BUFFERLIST* aBufferList) -{ - MOZ_ASSERT(!mMemoryDealer[aType].get()); - - // Get port definition. - OMX_PARAM_PORTDEFINITIONTYPE def; - nsTArray<uint32_t> portindex; - GetPortIndices(portindex); - for (auto idx : portindex) { - InitOmxParameter(&def); - def.nPortIndex = idx; - - OMX_ERRORTYPE err = GetParameter(OMX_IndexParamPortDefinition, - &def, - sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); - if (err != OMX_ErrorNone) { - return NS_ERROR_FAILURE; - } else if (def.eDir == aType) { - LOG("Get OMX_IndexParamPortDefinition: port: %d, type: %d", def.nPortIndex, def.eDir); - break; - } - } - - size_t t = 0; - - // Configure video output GraphicBuffer for video decoding acceleration. - bool useGralloc = false; - if (aType == OMX_DirOutput && mQuirks.test(kRequiresAllocateBufferOnOutputPorts) && - (def.eDomain == OMX_PortDomainVideo)) { - if (NS_FAILED(EnableOmxGraphicBufferPort(def))) { - return NS_ERROR_FAILURE; - } - - LOG("Enable OMX GraphicBuffer port, number %d, width %d, height %d", def.nBufferCountActual, - def.format.video.nFrameWidth, def.format.video.nFrameHeight); - - useGralloc = true; - - t = 1024; // MemoryDealer doesn't like 0, it's just for MemoryDealer happy. - } else { - t = def.nBufferCountActual * def.nBufferSize; - LOG("Buffer count %d, buffer size %d", def.nBufferCountActual, def.nBufferSize); - } - - bool liveinlocal = mOmx->livesLocally(mNode, getpid()); - - // MemoryDealer is a IPC buffer allocator in Gonk because IOMX is actually - // lives in mediaserver. - mMemoryDealer[aType] = new MemoryDealer(t, "Gecko-OMX"); - for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { - RefPtr<GonkBufferData> buffer; - IOMX::buffer_id bufferID; - status_t st; - nsresult rv; - - buffer = new GonkBufferData(liveinlocal, this); - if (useGralloc) { - // Buffer is lived remotely. Use GraphicBuffer for decoded video frame display. - rv = buffer->InitGraphicBuffer(def.format.video); - NS_ENSURE_SUCCESS(rv, rv); - st = mOmx->useGraphicBuffer(mNode, - def.nPortIndex, - buffer->mTextureClientRecycleHandler->GetGraphicBuffer(), - &bufferID); - CHECK_ERR(st); - } else { - sp<IMemory> mem = mMemoryDealer[aType]->allocate(def.nBufferSize); - MOZ_ASSERT(mem.get()); - - if ((mQuirks.test(kRequiresAllocateBufferOnInputPorts) && aType == OMX_DirInput) || - (mQuirks.test(kRequiresAllocateBufferOnOutputPorts) && aType == OMX_DirOutput)) { - // Buffer is lived remotely. We allocate a local OMX_BUFFERHEADERTYPE - // as the mirror of the remote OMX_BUFFERHEADERTYPE. - st = mOmx->allocateBufferWithBackup(mNode, aType, mem, &bufferID); - CHECK_ERR(st); - rv = buffer->InitSharedMemory(mem.get()); - NS_ENSURE_SUCCESS(rv, rv); - } else { - // Buffer is lived locally, bufferID is the actually OMX_BUFFERHEADERTYPE - // pointer. - st = mOmx->useBuffer(mNode, aType, mem, &bufferID); - CHECK_ERR(st); - rv = buffer->InitLocalBuffer(bufferID); - NS_ENSURE_SUCCESS(rv, rv); - } - } - - rv = buffer->SetBufferId(bufferID); - NS_ENSURE_SUCCESS(rv, rv); - - aBufferList->AppendElement(buffer); - } - - return NS_OK; -} - -nsresult -GonkOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType, - BUFFERLIST* aBufferList) -{ - status_t st; - uint32_t len = aBufferList->Length(); - for (uint32_t i = 0; i < len; i++) { - GonkBufferData* buffer = static_cast<GonkBufferData*>(aBufferList->ElementAt(i).get()); - IOMX::buffer_id id = (OMX_BUFFERHEADERTYPE*) buffer->ID(); - st = mOmx->freeBuffer(mNode, aType, id); - if (st != OK) { - return NS_ERROR_FAILURE; - } - buffer->ReleaseBuffer(); - } - aBufferList->Clear(); - mMemoryDealer[aType].clear(); - - return NS_OK; -} - -nsresult -GonkOmxPlatformLayer::EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef) -{ - status_t st; - - st = mOmx->enableGraphicBuffers(mNode, aDef.nPortIndex, OMX_TRUE); - CHECK_ERR(st); - - return NS_OK; -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::GetState(OMX_STATETYPE* aType) -{ - return (OMX_ERRORTYPE)mOmx->getState(mNode, aType); -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex, - OMX_PTR aComponentParameterStructure, - OMX_U32 aComponentParameterSize) -{ - return (OMX_ERRORTYPE)mOmx->getParameter(mNode, - aParamIndex, - aComponentParameterStructure, - aComponentParameterSize); -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex, - OMX_PTR aComponentParameterStructure, - OMX_U32 aComponentParameterSize) -{ - return (OMX_ERRORTYPE)mOmx->setParameter(mNode, - aParamIndex, - aComponentParameterStructure, - aComponentParameterSize); -} - -nsresult -GonkOmxPlatformLayer::Shutdown() -{ - mOmx->freeNode(mNode); - mOmxObserver->Shutdown(); - mOmxObserver = nullptr; - mOmxClient.disconnect(); - - return NS_OK; -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo) -{ - mInfo = aInfo; - status_t err = mOmxClient.connect(); - if (err != OK) { - return OMX_ErrorUndefined; - } - mOmx = mOmxClient.interface(); - if (!mOmx.get()) { - return OMX_ErrorUndefined; - } - - LOG("find componenet for mime type %s", mInfo->mMimeType.Data()); - - nsTArray<ComponentInfo> components; - if (FindComponents(mInfo->mMimeType, &components)) { - for (auto comp : components) { - if (LoadComponent(comp)) { - return OMX_ErrorNone; - } - } - } - - LOG("no component is loaded"); - return OMX_ErrorUndefined; -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::EmptyThisBuffer(BufferData* aData) -{ - return (OMX_ERRORTYPE)mOmx->emptyBuffer(mNode, - (IOMX::buffer_id)aData->ID(), - aData->mBuffer->nOffset, - aData->mBuffer->nFilledLen, - aData->mBuffer->nFlags, - aData->mBuffer->nTimeStamp); -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::FillThisBuffer(BufferData* aData) -{ - return (OMX_ERRORTYPE)mOmx->fillBuffer(mNode, (IOMX::buffer_id)aData->ID()); -} - -OMX_ERRORTYPE -GonkOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd, - OMX_U32 aParam1, - OMX_PTR aCmdData) -{ - return (OMX_ERRORTYPE)mOmx->sendCommand(mNode, aCmd, aParam1); -} - -bool -GonkOmxPlatformLayer::LoadComponent(const ComponentInfo& aComponent) -{ - status_t err = mOmx->allocateNode(aComponent.mName, mOmxObserver, &mNode); - if (err == OK) { - mQuirks = aComponent.mQuirks; - LOG("Load OpenMax component %s, alloc input %d, alloc output %d, live locally %d", - aComponent.mName, mQuirks.test(kRequiresAllocateBufferOnInputPorts), - mQuirks.test(kRequiresAllocateBufferOnOutputPorts), - mOmx->livesLocally(mNode, getpid())); - return true; - } - return false; -} - -layers::ImageContainer* -GonkOmxPlatformLayer::GetImageContainer() -{ - return mImageContainer; -} - -const TrackInfo* -GonkOmxPlatformLayer::GetTrackInfo() -{ - return mInfo; -} - -bool -GonkOmxPlatformLayer::FindComponents(const nsACString& aMimeType, - nsTArray<ComponentInfo>* aComponents) -{ - static const MediaCodecList* codecs = MediaCodecList::getInstance(); - - bool useHardwareCodecOnly = false; - - // H264 and H263 has different profiles, software codec doesn't support high profile. - // So we use hardware codec only. - if (!IsInEmulator() && - (aMimeType.EqualsLiteral("video/avc") || - aMimeType.EqualsLiteral("video/mp4") || - aMimeType.EqualsLiteral("video/mp4v-es") || - aMimeType.EqualsLiteral("video/3gp"))) { - useHardwareCodecOnly = true; - } - - const char* mime = aMimeType.Data(); - // Translate VP8 MIME type to Android format. - if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) { - mime = "video/x-vnd.on2.vp8"; - } - - size_t start = 0; - bool found = false; - while (true) { - ssize_t index = codecs->findCodecByType(mime, false /* encoder */, start); - if (index < 0) { - break; - } - start = index + 1; - - const char* name = codecs->getCodecName(index); - if (IsSoftwareCodec(name) && useHardwareCodecOnly) { - continue; - } - - found = true; - - if (!aComponents) { - continue; - } - ComponentInfo* comp = aComponents->AppendElement(); - comp->mName = name; - if (codecs->codecHasQuirk(index, "requires-allocate-on-input-ports")) { - comp->mQuirks.set(kRequiresAllocateBufferOnInputPorts); - } - if (codecs->codecHasQuirk(index, "requires-allocate-on-output-ports")) { - comp->mQuirks.set(kRequiresAllocateBufferOnOutputPorts); - } - } - - return found; -} - -OMX_VIDEO_CODINGTYPE -GonkOmxPlatformLayer::CompressionFormat() -{ - MOZ_ASSERT(mInfo); - - return mInfo->mMimeType.EqualsLiteral("video/webm; codecs=vp8") ? - ANDROID_OMX_VIDEO_CodingVP8 : OmxPlatformLayer::CompressionFormat(); -} - -} // mozilla diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.h b/dom/media/platforms/omx/GonkOmxPlatformLayer.h deleted file mode 100644 index aaa8c654d..000000000 --- a/dom/media/platforms/omx/GonkOmxPlatformLayer.h +++ /dev/null @@ -1,205 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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 !defined(GonkOmxPlatformLayer_h_) -#define GonkOmxPlatformLayer_h_ - -#pragma GCC visibility push(default) - -#include <bitset> - -#include <utils/RefBase.h> -#include <media/stagefright/OMXClient.h> -#include "nsAutoPtr.h" - -#include "OMX_Component.h" - -#include "OmxPlatformLayer.h" - -class nsACString; - -namespace android { -class IMemory; -class MemoryDealer; -} - -namespace mozilla { - -class GonkOmxObserver; -class GonkOmxPlatformLayer; -class GonkTextureClientRecycleHandler; - -/* - * Due to Android's omx node could live in local process (client) or remote - * process (mediaserver). And there are 3 kinds of buffer in Android OMX. - * - * 1. - * When buffer is in local process, the IOMX::buffer_id is OMX_BUFFERHEADERTYPE - * pointer actually, it is safe to use it directly. - * - * 2. - * When buffer is in remote process, the OMX_BUFFERHEADERTYPE pointer is 'IN' the - * remote process. It can't be used in local process, so here it allocates a - * local OMX_BUFFERHEADERTYPE. The raw/decoded data is in the android shared - * memory, IMemory. - * - * 3. - * When buffer is in remote process for the display output port. It uses - * GraphicBuffer to accelerate the decoding and display. - * - */ -class GonkBufferData : public OmxPromiseLayer::BufferData { -protected: - virtual ~GonkBufferData() {} - -public: - GonkBufferData(bool aLiveInLocal, - GonkOmxPlatformLayer* aLayer); - - BufferID ID() override - { - return mId; - } - - already_AddRefed<MediaData> GetPlatformMediaData() override; - - bool IsLocalBuffer() - { - return !!mMirrorBuffer.get(); - } - - void ReleaseBuffer(); - - nsresult SetBufferId(android::IOMX::buffer_id aId) - { - mId = aId; - return NS_OK; - } - - // The mBuffer is in local process. And aId is actually the OMX_BUFFERHEADERTYPE - // pointer. It doesn't need a mirror buffer. - nsresult InitLocalBuffer(android::IOMX::buffer_id aId); - - // aMemory is an IPC based memory which will be used as the pBuffer in - // mBuffer. And the mBuffer will be the mirror OMX_BUFFERHEADERTYPE - // of the one in the remote process. - nsresult InitSharedMemory(android::IMemory* aMemory); - - // GraphicBuffer is for video decoding acceleration on output port. - // Then mBuffer is the mirror OMX_BUFFERHEADERTYPE of the one in the remote - // process. - nsresult InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef); - - // Android OMX uses this id to pass the buffer between OMX component and - // client. - android::IOMX::buffer_id mId; - - // mMirrorBuffer are used only when the omx node is in mediaserver. - // Due to IPC problem, the mId is the OMX_BUFFERHEADERTYPE address in mediaserver. - // It can't mapping to client process, so we need a local OMX_BUFFERHEADERTYPE - // here to mirror the remote OMX_BUFFERHEADERTYPE in mediaserver. - nsAutoPtr<OMX_BUFFERHEADERTYPE> mMirrorBuffer; - - // It creates GraphicBuffer and manages TextureClient. - RefPtr<GonkTextureClientRecycleHandler> mTextureClientRecycleHandler; - - GonkOmxPlatformLayer* mGonkPlatformLayer; -}; - -class GonkOmxPlatformLayer : public OmxPlatformLayer { -public: - enum { - kRequiresAllocateBufferOnInputPorts = 0, - kRequiresAllocateBufferOnOutputPorts, - QUIRKS, - }; - typedef std::bitset<QUIRKS> Quirks; - - struct ComponentInfo { - const char* mName; - Quirks mQuirks; - }; - - GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder, - OmxPromiseLayer* aPromiseLayer, - TaskQueue* aTaskQueue, - layers::ImageContainer* aImageContainer); - - nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override; - - nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override; - - OMX_ERRORTYPE GetState(OMX_STATETYPE* aType) override; - - OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex, - OMX_PTR aComponentParameterStructure, - OMX_U32 aComponentParameterSize) override; - - OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex, - OMX_PTR aComponentParameterStructure, - OMX_U32 aComponentParameterSize) override; - - OMX_ERRORTYPE InitOmxToStateLoaded(const TrackInfo* aInfo) override; - - OMX_ERRORTYPE EmptyThisBuffer(BufferData* aData) override; - - OMX_ERRORTYPE FillThisBuffer(BufferData* aData) override; - - OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE aCmd, - OMX_U32 aParam1, - OMX_PTR aCmdData) override; - - nsresult Shutdown() override; - - static bool FindComponents(const nsACString& aMimeType, - nsTArray<ComponentInfo>* aComponents = nullptr); - - // Android/QCOM decoder uses its own OMX_VIDEO_CodingVP8 definition in - // frameworks/native/media/include/openmax/OMX_Video.h, not the one defined - // in OpenMAX v1.1.2 OMX_VideoExt.h - OMX_VIDEO_CODINGTYPE CompressionFormat() override; - -protected: - friend GonkBufferData; - - layers::ImageContainer* GetImageContainer(); - - const TrackInfo* GetTrackInfo(); - - TaskQueue* GetTaskQueue() - { - return mTaskQueue; - } - - nsresult EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef); - - bool LoadComponent(const ComponentInfo& aComponent); - - friend class GonkOmxObserver; - - RefPtr<TaskQueue> mTaskQueue; - - RefPtr<layers::ImageContainer> mImageContainer; - - // OMX_DirInput is 0, OMX_DirOutput is 1. - android::sp<android::MemoryDealer> mMemoryDealer[2]; - - android::sp<GonkOmxObserver> mOmxObserver; - - android::sp<android::IOMX> mOmx; - - android::IOMX::node_id mNode; - - android::OMXClient mOmxClient; - - Quirks mQuirks; -}; - -} - -#pragma GCC visibility pop - -#endif // GonkOmxPlatformLayer_h_ diff --git a/dom/media/platforms/omx/OmxPlatformLayer.cpp b/dom/media/platforms/omx/OmxPlatformLayer.cpp index d1f43144d..039b4a22f 100644 --- a/dom/media/platforms/omx/OmxPlatformLayer.cpp +++ b/dom/media/platforms/omx/OmxPlatformLayer.cpp @@ -8,11 +8,6 @@ #include "OMX_VideoExt.h" // For VP8. -#if defined(MOZ_WIDGET_GONK) && (ANDROID_VERSION == 20 || ANDROID_VERSION == 19) -#define OMX_PLATFORM_GONK -#include "GonkOmxPlatformLayer.h" -#endif - #include "VPXDecoder.h" #ifdef LOG diff --git a/dom/media/platforms/omx/moz.build b/dom/media/platforms/omx/moz.build index 9f641d937..661e280e0 100644 --- a/dom/media/platforms/omx/moz.build +++ b/dom/media/platforms/omx/moz.build @@ -21,29 +21,6 @@ LOCAL_INCLUDES += [ include('/ipc/chromium/chromium-config.mozbuild') -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and (CONFIG['ANDROID_VERSION'] == '19' or CONFIG['ANDROID_VERSION'] == '20'): - # Suppress some GCC/clang warnings being treated as errors: - # - about attributes on forward declarations for types that are already - # defined, which complains about an important MOZ_EXPORT for android::AString - # - about multi-character constants which are used in codec-related code - if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: - CXXFLAGS += [ - '-Wno-error=attributes', - '-Wno-error=multichar' - ] - CXXFLAGS += [ - '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [ - 'frameworks/base/include/binder', - 'frameworks/base/include/utils', - ] - ] - UNIFIED_SOURCES += [ - 'GonkOmxPlatformLayer.cpp', - ] - EXTRA_DSO_LDOPTS += [ - '-libbinder', - ] - FINAL_LIBRARY = 'xul' if CONFIG['GNU_CXX']: diff --git a/dom/media/standalone/moz.build b/dom/media/standalone/moz.build index 5d2c5a6e7..959703765 100644 --- a/dom/media/standalone/moz.build +++ b/dom/media/standalone/moz.build @@ -4,7 +4,7 @@ # 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['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': +if CONFIG['OS_TARGET'] != 'WINNT': Library('media_standalone') UNIFIED_SOURCES += [ diff --git a/dom/media/systemservices/MediaSystemResourceService.cpp b/dom/media/systemservices/MediaSystemResourceService.cpp index 0e5d6a50c..4434c54c2 100644 --- a/dom/media/systemservices/MediaSystemResourceService.cpp +++ b/dom/media/systemservices/MediaSystemResourceService.cpp @@ -47,23 +47,6 @@ MediaSystemResourceService::MediaSystemResourceService() : mDestroyed(false) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); -#ifdef MOZ_WIDGET_GONK - // The maximum number of hardware resoureces available. - // XXX need to hange to a dynamic way. - enum - { - VIDEO_DECODER_COUNT = 1, - VIDEO_ENCODER_COUNT = 1 - }; - - MediaSystemResource* resource; - - resource = new MediaSystemResource(VIDEO_DECODER_COUNT); - mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_DECODER), resource); - - resource = new MediaSystemResource(VIDEO_ENCODER_COUNT); - mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_ENCODER), resource); -#endif } MediaSystemResourceService::~MediaSystemResourceService() diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build index 33e5ed1f1..82a5c5e72 100644 --- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -42,16 +42,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': UNIFIED_SOURCES += ['OSXRunLoopSingleton.cpp'] EXPORTS += ['OSXRunLoopSingleton.h'] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - if CONFIG['ANDROID_VERSION'] >= '17': - LOCAL_INCLUDES += [ - '%' + '%s/frameworks/wilhelm/include' % CONFIG['ANDROID_SOURCE'], - ] - else: - LOCAL_INCLUDES += [ - '%' + '%s/system/media/wilhelm/include' % CONFIG['ANDROID_SOURCE'], - ] - if CONFIG['_MSC_VER']: DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' diff --git a/dom/media/webrtc/MediaEngine.h b/dom/media/webrtc/MediaEngine.h index ff2a6e25a..6a6988544 100644 --- a/dom/media/webrtc/MediaEngine.h +++ b/dom/media/webrtc/MediaEngine.h @@ -54,11 +54,8 @@ public: static const int DEFAULT_169_VIDEO_WIDTH = 1280; static const int DEFAULT_169_VIDEO_HEIGHT = 720; -#ifndef MOZ_B2G static const int DEFAULT_SAMPLE_RATE = 32000; -#else - static const int DEFAULT_SAMPLE_RATE = 16000; -#endif + // This allows using whatever rate the graph is using for the // MediaStreamTrack. This is useful for microphone data, we know it's already // at the correct rate for insertion in the MSG. diff --git a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp index a0f31d937..e1e572724 100644 --- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp @@ -325,7 +325,7 @@ MediaEngineCameraVideoSource::SetName(nsString aName) VideoFacingModeEnum facingMode = VideoFacingModeEnum::User; // Set facing mode based on device name. -#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) +#if defined(ANDROID) // Names are generated. Example: "Camera 0, Facing back, Orientation 90" // // See media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/ diff --git a/dom/media/webrtc/MediaEngineDefault.cpp b/dom/media/webrtc/MediaEngineDefault.cpp index 9c97d197f..eb0ac2b6f 100644 --- a/dom/media/webrtc/MediaEngineDefault.cpp +++ b/dom/media/webrtc/MediaEngineDefault.cpp @@ -192,7 +192,7 @@ MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID, mTrackID = aID; // Start timer for subsequent frames -#if (defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)) && defined(DEBUG) +#if defined(MOZ_WIDGET_ANDROID) && defined(DEBUG) // emulator debug is very, very slow and has problems dealing with realtime audio inputs mTimer->InitWithCallback(this, (1000 / mOpts.mFPS)*10, nsITimer::TYPE_REPEATING_SLACK); #else diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp index 1a2dc9a04..a77800424 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.cpp +++ b/dom/media/webrtc/MediaEngineWebRTC.cpp @@ -335,7 +335,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource, int nDevices = 0; mAudioInput->GetNumOfRecordingDevices(nDevices); int i; -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) i = 0; // Bug 1037025 - let the OS handle defaulting for now on android/b2g #else // -1 is "default communications device" depending on OS in webrtc.org code diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp index 0b8796aa8..1e2e13d01 100644 --- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -741,9 +741,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel() // Check for availability. if (!mAudioInput->SetRecordingDevice(mCapIndex)) { -#ifndef MOZ_B2G - // Because of the permission mechanism of B2G, we need to skip the status - // check here. bool avail = false; mAudioInput->GetRecordingDeviceStatus(avail); if (!avail) { @@ -752,7 +749,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel() } return false; } -#endif // MOZ_B2G // Set "codec" to PCM, 32kHz on 1 channel ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine)); |