void CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (mFront) { mPrevFront = mFront; mFront = nullptr; } auto gl = aLayer->mGLContext; gl->MakeCurrent(); if (aLayer->mGLFrontbuffer) { mFront = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get()); if (mFront) mFront->Surf()->Fence(); } else { mFront = gl->Screen()->Front(); if (!mFront) return; } MOZ_ASSERT(mFront); // Alright, now sort out the IPC goop. SharedSurface* surf = mFront->Surf(); auto forwarder = GetForwarder(); auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE; // Get a TexClient from our surf. RefPtr<TextureClient> newTex = TexClientFromShSurf(surf, flags); if (!newTex) { auto manager = aLayer->ClientManager(); auto shadowForwarder = manager->AsShadowForwarder(); auto layersBackend = shadowForwarder->GetCompositorBackendType(); newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend); } MOZ_ASSERT(newTex); // Add the new TexClient. MOZ_ALWAYS_TRUE( newTex->InitIPDLActor(forwarder) ); MOZ_ASSERT(newTex->GetIPDLActor()); // Remove the old TexClient. if (mFrontTex) { // remove old buffer from CompositableHost RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker(); // Hold TextureClient until transaction complete. tracker->SetTextureClient(mFrontTex); mFrontTex->SetRemoveFromCompositableTracker(tracker); // RemoveTextureFromCompositableAsync() expects CompositorChild's presence. GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex); mFrontTex = nullptr; } // Use the new TexClient. mFrontTex = newTex; forwarder->UpdatedTexture(this, mFrontTex, nullptr); forwarder->UseTexture(this, mFrontTex); }
Result<Ok, nsresult> Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, uint64_t* aDecodeTime, bool aIsAudio) { if (!aTfhd.IsValid() || !aMvhd.IsValid() || !aMdhd.IsValid() || !aEdts.IsValid()) { LOG(Moof, "Invalid dependencies: aTfhd(%d) aMvhd(%d) aMdhd(%d) aEdts(%d)", aTfhd.IsValid(), aMvhd.IsValid(), aMdhd.IsValid(), !aEdts.IsValid()); return Err(NS_ERROR_FAILURE); } BoxReader reader(aBox); if (!reader->CanReadType<uint32_t>()) { LOG(Moof, "Incomplete Box (missing flags)"); return Err(NS_ERROR_FAILURE); } uint32_t flags; MOZ_TRY_VAR(flags, reader->ReadU32()); uint8_t version = flags >> 24; if (!reader->CanReadType<uint32_t>()) { LOG(Moof, "Incomplete Box (missing sampleCount)"); return Err(NS_ERROR_FAILURE); } uint32_t sampleCount; MOZ_TRY_VAR(sampleCount, reader->ReadU32()); if (sampleCount == 0) { return Ok(); } uint64_t offset = aTfhd.mBaseDataOffset; if (flags & 0x01) { uint32_t tmp; MOZ_TRY_VAR(tmp, reader->ReadU32()); offset += tmp; } uint32_t firstSampleFlags = aTfhd.mDefaultSampleFlags; if (flags & 0x04) { MOZ_TRY_VAR(firstSampleFlags, reader->ReadU32()); } uint64_t decodeTime = *aDecodeTime; nsTArray<MP4Interval<Microseconds>> timeRanges; if (!mIndex.SetCapacity(sampleCount, fallible)) { LOG(Moof, "Out of Memory"); return Err(NS_ERROR_FAILURE); } for (size_t i = 0; i < sampleCount; i++) { uint32_t sampleDuration = aTfhd.mDefaultSampleDuration; if (flags & 0x100) { MOZ_TRY_VAR(sampleDuration, reader->ReadU32()); } uint32_t sampleSize = aTfhd.mDefaultSampleSize; if (flags & 0x200) { MOZ_TRY_VAR(sampleSize, reader->ReadU32()); } uint32_t sampleFlags = i ? aTfhd.mDefaultSampleFlags : firstSampleFlags; if (flags & 0x400) { MOZ_TRY_VAR(sampleFlags, reader->ReadU32()); } int32_t ctsOffset = 0; if (flags & 0x800) { MOZ_TRY_VAR(ctsOffset, reader->Read32()); } if (sampleSize) { Sample sample; sample.mByteRange = MediaByteRange(offset, offset + sampleSize); offset += sampleSize; Microseconds decodeOffset, emptyOffset, startCts, endCts; MOZ_TRY_VAR(decodeOffset, aMdhd.ToMicroseconds((int64_t)decodeTime - aEdts.mMediaStart)); MOZ_TRY_VAR(emptyOffset, aMvhd.ToMicroseconds(aEdts.mEmptyOffset)); sample.mDecodeTime = decodeOffset + emptyOffset; MOZ_TRY_VAR(startCts, aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset - aEdts.mMediaStart)); MOZ_TRY_VAR(endCts, aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset + sampleDuration - aEdts.mMediaStart)); sample.mCompositionRange = MP4Interval<Microseconds>(startCts + emptyOffset, endCts + emptyOffset); // Sometimes audio streams don't properly mark their samples as keyframes, // because every audio sample is a keyframe. sample.mSync = !(sampleFlags & 0x1010000) || aIsAudio; // FIXME: Make this infallible after bug 968520 is done. MOZ_ALWAYS_TRUE(mIndex.AppendElement(sample, fallible)); mMdatRange = mMdatRange.Span(sample.mByteRange); } decodeTime += sampleDuration; } Microseconds roundTime; MOZ_TRY_VAR(roundTime, aMdhd.ToMicroseconds(sampleCount)); mMaxRoundingError += roundTime; *aDecodeTime = decodeTime; return Ok(); }
bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName, WebGLTexture* tex, TexImageTarget target, GLint level, const webgl::DriverUnpackInfo* dstDUI, GLint xOffset, GLint yOffset, GLint zOffset, GLenum* const out_error) const { const auto& webgl = tex->mContext; //// const auto rowLength = mSurf->GetSize().width; const auto rowCount = mSurf->GetSize().height; const auto& dstPI = dstDUI->ToPacking(); const auto& dstBPP = webgl::BytesPerPixel(dstPI); const auto dstFormat = FormatForPackingInfo(dstPI); //// WebGLTexelFormat srcFormat; uint8_t srcBPP; if (!GetFormatForSurf(mSurf, &srcFormat, &srcBPP)) { webgl->ErrorImplementationBug("%s: GetFormatForSurf failed for" " WebGLTexelFormat::%u.", funcName, uint32_t(mSurf->GetFormat())); return false; } gfx::DataSourceSurface::ScopedMap map(mSurf, gfx::DataSourceSurface::MapType::READ); if (!map.IsMapped()) { webgl->ErrorOutOfMemory("%s: Failed to map source surface for upload.", funcName); return false; } const auto& srcBegin = map.GetData(); const auto& srcStride = map.GetStride(); //// const auto srcRowLengthBytes = rowLength * srcBPP; const uint8_t maxGLAlignment = 8; uint8_t srcAlignment = 1; for (; srcAlignment <= maxGLAlignment; srcAlignment *= 2) { const auto strideGuess = RoundUpToMultipleOf(srcRowLengthBytes, srcAlignment); if (strideGuess == srcStride) break; } const uint32_t dstAlignment = (srcAlignment > maxGLAlignment) ? 1 : srcAlignment; const auto dstRowLengthBytes = rowLength * dstBPP; const auto dstStride = RoundUpToMultipleOf(dstRowLengthBytes, dstAlignment); //// const uint8_t* dstBegin = srcBegin; UniqueBuffer tempBuffer; if (!ConvertIfNeeded(webgl, funcName, rowLength, rowCount, srcFormat, srcBegin, srcStride, dstFormat, dstStride, &dstBegin, &tempBuffer)) { return false; } //// const auto& gl = webgl->gl; MOZ_ALWAYS_TRUE( gl->MakeCurrent() ); gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, dstAlignment); if (webgl->IsWebGL2()) { gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength); } *out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dstDUI, xOffset, yOffset, zOffset, mWidth, mHeight, mDepth, dstBegin); gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, webgl->mPixelStore_UnpackAlignment); if (webgl->IsWebGL2()) { gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, webgl->mPixelStore_UnpackRowLength); } return true; }
static TemporaryRef<TextureClient> TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator, TextureFlags baseFlags, LayersBackend layersBackend) { auto backendType = gfx::BackendType::CAIRO; TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType, baseFlags, layersBackend); RefPtr<BufferTextureClient> texClient; { gl::ScopedReadbackFB autoReadback(src); // We have a source FB, now we need a format. GLenum destFormat = LOCAL_GL_BGRA; GLenum destType = LOCAL_GL_UNSIGNED_BYTE; GLenum readFormat; GLenum readType; // We actually don't care if they match, since we can handle // any read{Format,Type} we get. auto gl = src->mGL; GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType); MOZ_ASSERT(readFormat == LOCAL_GL_RGBA || readFormat == LOCAL_GL_BGRA); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); // With a format and type, we can create texClient. if (readFormat == LOCAL_GL_BGRA && readType == LOCAL_GL_UNSIGNED_BYTE) { // 0xAARRGGBB // In Lendian: [BB, GG, RR, AA] texClient = factory.CreateB8G8R8AX8(); } else if (readFormat == LOCAL_GL_RGBA && readType == LOCAL_GL_UNSIGNED_BYTE) { // [RR, GG, BB, AA] texClient = factory.CreateR8G8B8AX8(); } else { MOZ_CRASH("Bad `read{Format,Type}`."); } MOZ_ASSERT(texClient); if (!texClient) return nullptr; // With a texClient, we can lock for writing. MOZ_ALWAYS_TRUE( texClient->Lock(OpenMode::OPEN_WRITE) ); uint8_t* lockedBytes = texClient->GetLockedData(); // ReadPixels from the current FB into lockedBits. auto width = src->mSize.width; auto height = src->mSize.height; { ScopedPackAlignment autoAlign(gl, 4); gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, lockedBytes); } // RB_SWAPPED doesn't work with D3D11. (bug 1051010) // RB_SWAPPED doesn't work with Basic. (bug ???????) // RB_SWAPPED doesn't work with D3D9. (bug ???????) bool layersNeedsManualSwap = layersBackend == LayersBackend::LAYERS_BASIC || layersBackend == LayersBackend::LAYERS_D3D9 || layersBackend == LayersBackend::LAYERS_D3D11; if (texClient->HasFlags(TextureFlags::RB_SWAPPED) && layersNeedsManualSwap) { size_t pixels = width * height; uint8_t* itr = lockedBytes; for (size_t i = 0; i < pixels; i++) { SwapRB_R8G8B8A8(itr); itr += 4; } texClient->RemoveFlags(TextureFlags::RB_SWAPPED); } texClient->Unlock(); } return texClient.forget(); }
// static nsresult IDBFactory::AllowedForWindowInternal(nsPIDOMWindow* aWindow, nsIPrincipal** aPrincipal) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aWindow); MOZ_ASSERT(aWindow->IsInnerWindow()); if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsIDocument* document = aWindow->GetExtantDoc(); if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) { return NS_ERROR_DOM_SECURITY_ERR; } nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow); MOZ_ASSERT(sop); nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal(); if (NS_WARN_IF(!principal)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (nsContentUtils::IsSystemPrincipal(principal)) { principal.forget(aPrincipal); return NS_OK; } bool isNullPrincipal; if (NS_WARN_IF(NS_FAILED(principal->GetIsNullPrincipal(&isNullPrincipal))) || isNullPrincipal) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } // Whitelist about:home, since it doesn't have a base domain it would not // pass the ThirdPartyUtil check, though it should be able to use indexedDB. bool skipThirdPartyCheck = false; nsCOMPtr<nsIURI> uri; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(principal->GetURI(getter_AddRefs(uri)))); bool isAbout; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uri->SchemeIs("about", &isAbout))); if (isAbout) { nsCOMPtr<nsIAboutModule> module; if (NS_SUCCEEDED(NS_GetAboutModule(uri, getter_AddRefs(module)))) { uint32_t flags; if (NS_SUCCEEDED(module->GetURIFlags(uri, &flags))) { skipThirdPartyCheck = flags & nsIAboutModule::ENABLE_INDEXED_DB; } else { NS_WARNING("GetURIFlags failed!"); } } else { NS_WARNING("NS_GetAboutModule failed!"); } } if (!skipThirdPartyCheck) { nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID); MOZ_ASSERT(thirdPartyUtil); bool isThirdParty; if (NS_WARN_IF(NS_FAILED( thirdPartyUtil->IsThirdPartyWindow(aWindow, nullptr, &isThirdParty)))) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (isThirdParty) { return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } } principal.forget(aPrincipal); return NS_OK; }
already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(nsIPrincipal* aPrincipal, const nsAString& aName, const Optional<uint64_t>& aVersion, const Optional<StorageType>& aStorageType, bool aDeleting, ErrorResult& aRv) { MOZ_ASSERT(mWindow || mOwningObject); MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode); CommonFactoryRequestParams commonParams; commonParams.privateBrowsingMode() = mPrivateBrowsingMode; PrincipalInfo& principalInfo = commonParams.principalInfo(); if (aPrincipal) { if (!NS_IsMainThread()) { MOZ_CRASH("Figure out security checks for workers!"); } MOZ_ASSERT(nsContentUtils::IsCallerChrome()); if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal, &principalInfo)))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo && principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } } else { principalInfo = *mPrincipalInfo; } uint64_t version = 0; if (!aDeleting && aVersion.WasPassed()) { if (aVersion.Value() < 1) { aRv.ThrowTypeError(MSG_INVALID_VERSION); return nullptr; } version = aVersion.Value(); } // Nothing can be done here if we have previously failed to create a // background actor. if (mBackgroundActorFailed) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } PersistenceType persistenceType; if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { // Chrome privilege always gets persistent storage. persistenceType = PERSISTENCE_TYPE_PERSISTENT; } else { persistenceType = PersistenceTypeFromStorage(aStorageType); } DatabaseMetadata& metadata = commonParams.metadata(); metadata.name() = aName; metadata.persistenceType() = persistenceType; FactoryRequestParams params; if (aDeleting) { metadata.version() = 0; params = DeleteDatabaseRequestParams(commonParams); } else { metadata.version() = version; params = OpenDatabaseRequestParams(commonParams); } if (!mBackgroundActor && mPendingRequests.IsEmpty()) { // We need to start the sequence to create a background actor for this // thread. BackgroundChildImpl::ThreadLocal* threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); nsAutoPtr<ThreadLocal> newIDBThreadLocal; ThreadLocal* idbThreadLocal; if (threadLocal && threadLocal->mIndexedDBThreadLocal) { idbThreadLocal = threadLocal->mIndexedDBThreadLocal; } else { nsCOMPtr<nsIUUIDGenerator> uuidGen = do_GetService("@mozilla.org/uuid-generator;1"); MOZ_ASSERT(uuidGen); nsID id; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uuidGen->GenerateUUIDInPlace(&id))); newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id); } nsRefPtr<BackgroundCreateCallback> cb = new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo()); if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } if (newIDBThreadLocal) { if (!threadLocal) { threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); } MOZ_ASSERT(threadLocal); MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal); threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget(); } } AutoJSAPI autoJS; nsRefPtr<IDBOpenDBRequest> request; if (mWindow) { AutoJSContext cx; if (NS_WARN_IF(!autoJS.Init(mWindow, cx))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } JS::Rooted<JSObject*> scriptOwner(cx, static_cast<nsGlobalWindow*>(mWindow.get())->FastGetGlobalJSObject()); MOZ_ASSERT(scriptOwner); request = IDBOpenDBRequest::CreateForWindow(this, mWindow, scriptOwner); } else { autoJS.Init(mOwningObject.get()); JS::Rooted<JSObject*> scriptOwner(autoJS.cx(), mOwningObject); request = IDBOpenDBRequest::CreateForJS(this, scriptOwner); } MOZ_ASSERT(request); if (aDeleting) { IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " "indexedDB.deleteDatabase(\"%s\")", "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()", IDB_LOG_ID_STRING(), request->LoggingSerialNumber(), NS_ConvertUTF16toUTF8(aName).get()); } else { IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " "indexedDB.open(\"%s\", %s)", "IndexedDB %s: C R[%llu]: IDBFactory.open()", IDB_LOG_ID_STRING(), request->LoggingSerialNumber(), NS_ConvertUTF16toUTF8(aName).get(), IDB_LOG_STRINGIFY(aVersion)); } // If we already have a background actor then we can start this request now. if (mBackgroundActor) { nsresult rv = InitiateRequest(request, params); if (NS_WARN_IF(NS_FAILED(rv))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } } else { mPendingRequests.AppendElement(new PendingRequestInfo(request, params)); } return request.forget(); }
void UnmapPages(void *p, size_t size) { MOZ_ALWAYS_TRUE(0 == munmap((caddr_t)p, size)); }
void UnmapPages(void *p, size_t size) { MOZ_ALWAYS_TRUE(VirtualFree(p, 0, MEM_RELEASE)); }
nsresult PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo* aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipalInfo); bool isNullPointer; nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPointer); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isNullPointer) { *aPrincipalInfo = NullPrincipalInfo(); return NS_OK; } nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool isSystemPrincipal; rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isSystemPrincipal) { *aPrincipalInfo = SystemPrincipalInfo(); return NS_OK; } // might be an expanded principal nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal); if (expanded) { nsTArray<PrincipalInfo> whitelistInfo; PrincipalInfo info; nsTArray< nsCOMPtr<nsIPrincipal> >* whitelist; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(expanded->GetWhiteList(&whitelist))); for (uint32_t i = 0; i < whitelist->Length(); i++) { rv = PrincipalToPrincipalInfo((*whitelist)[i], &info); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // append that spec to the whitelist whitelistInfo.AppendElement(info); } *aPrincipalInfo = ExpandedPrincipalInfo(Move(whitelistInfo)); return NS_OK; } // must be a content principal nsCOMPtr<nsIURI> uri; rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!uri)) { return NS_ERROR_FAILURE; } nsCString spec; rv = uri->GetSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } *aPrincipalInfo = ContentPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(), spec); return NS_OK; }
int NrIceResolver::cancel(void *obj, void *handle) { MOZ_ALWAYS_TRUE(obj); MOZ_ASSERT(handle); ASSERT_ON_THREAD(static_cast<NrIceResolver *>(obj)->sts_thread_); return static_cast<PendingResolution *>(handle)->cancel(); }
/* statis */ nsTArray<UniquePtr<TrackInfo>> MP4Decoder::GetTracksInfo(const MediaContainerType& aType, MediaResult& aError) { nsTArray<UniquePtr<TrackInfo>> tracks; if (!IsTypeValid(aType)) { aError = MediaResult( NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Invalid type:%s", aType.Type().AsString().get())); return tracks; } aError = NS_OK; const MediaCodecs& codecs = aType.ExtendedType().Codecs(); if (codecs.IsEmpty()) { return tracks; } const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/mp4") || aType.Type() == MEDIAMIMETYPE("video/quicktime") || aType.Type() == MEDIAMIMETYPE("video/x-m4v"); for (const auto& codec : codecs.Range()) { if (IsAACCodecString(codec)) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/mp4a-latm"), aType)); continue; } if (codec.EqualsLiteral("mp3")) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/mpeg"), aType)); continue; } if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("flac")) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/") + NS_ConvertUTF16toUTF8(codec), aType)); continue; } if (IsVP9CodecString(codec)) { auto trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("video/vp9"), aType); uint8_t profile = 0; uint8_t level = 0; uint8_t bitDepth = 0; if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) { trackInfo->GetAsVideoInfo()->mColorDepth = gfx::ColorDepthForBitDepth(bitDepth); } tracks.AppendElement(std::move(trackInfo)); continue; } #ifdef MOZ_AV1 if (IsAV1CodecString(codec)) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("video/av1"), aType)); continue; } #endif if (isVideo && IsWhitelistedH264Codec(codec)) { auto trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("video/avc"), aType); uint8_t profile = 0, constraint = 0, level = 0; MOZ_ALWAYS_TRUE( ExtractH264CodecDetails(codec, profile, constraint, level)); uint32_t width = aType.ExtendedType().GetWidth().refOr(1280); uint32_t height = aType.ExtendedType().GetHeight().refOr(720); trackInfo->GetAsVideoInfo()->mExtraData = H264::CreateExtraData(profile, constraint, level, { width, height }); tracks.AppendElement(std::move(trackInfo)); continue; } // Unknown codec aError = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Unknown codec:%s", NS_ConvertUTF16toUTF8(codec).get())); } return tracks; }