void VideoFrameContainer::SetCurrentFrames(const VideoSegment& aSegment) { if (aSegment.IsEmpty()) { return; } MutexAutoLock lock(mMutex); // Collect any new frames produced in this iteration. AutoTArray<ImageContainer::NonOwningImage,4> newImages; PrincipalHandle lastPrincipalHandle = PRINCIPAL_HANDLE_NONE; VideoSegment::ConstChunkIterator iter(aSegment); while (!iter.IsEnded()) { VideoChunk chunk = *iter; const VideoFrame* frame = &chunk.mFrame; if (*frame == mLastPlayedVideoFrame) { iter.Next(); continue; } Image* image = frame->GetImage(); CONTAINER_LOG(LogLevel::Verbose, ("VideoFrameContainer %p writing video frame %p (%d x %d)", this, image, frame->GetIntrinsicSize().width, frame->GetIntrinsicSize().height)); if (frame->GetForceBlack()) { if (!mBlackImage) { mBlackImage = GetImageContainer()->CreatePlanarYCbCrImage(); if (mBlackImage) { // Sets the image to a single black pixel, which will be scaled to // fill the rendered size. SetImageToBlackPixel(mBlackImage->AsPlanarYCbCrImage()); } } if (mBlackImage) { image = mBlackImage; } } // Don't append null image to the newImages. if (!image) { iter.Next(); continue; } newImages.AppendElement(ImageContainer::NonOwningImage(image, chunk.mTimeStamp)); lastPrincipalHandle = chunk.GetPrincipalHandle(); mLastPlayedVideoFrame = *frame; iter.Next(); } // Don't update if there are no changes. if (newImages.IsEmpty()) { return; } AutoTArray<ImageContainer::NonOwningImage,4> images; bool principalHandleChanged = lastPrincipalHandle != PRINCIPAL_HANDLE_NONE && lastPrincipalHandle != GetLastPrincipalHandleLocked(); // Add the frames from this iteration. for (auto& image : newImages) { image.mFrameID = NewFrameID(); images.AppendElement(image); } if (principalHandleChanged) { UpdatePrincipalHandleForFrameIDLocked(lastPrincipalHandle, newImages.LastElement().mFrameID); } SetCurrentFramesLocked(mLastPlayedVideoFrame.GetIntrinsicSize(), images); nsCOMPtr<nsIRunnable> event = new VideoFrameContainerInvalidateRunnable(this); mMainThread->Dispatch(event.forget()); images.ClearAndRetainStorage(); }
bool IsInterfaceEqualToOrInheritedFrom(REFIID aInterface, REFIID aFrom, unsigned long aVtableIndexHint) { if (aInterface == aFrom) { return true; } // We expect this array to be length 1 but that is not guaranteed by the API. AutoTArray<RefPtr<ITypeInfo>, 1> typeInfos; // Grab aInterface's ITypeInfo so that we may obtain information about its // inheritance hierarchy. RefPtr<ITypeInfo> typeInfo; if (RegisteredProxy::Find(aInterface, getter_AddRefs(typeInfo))) { typeInfos.AppendElement(Move(typeInfo)); } /** * The main loop of this function searches the hierarchy of aInterface's * parent interfaces, searching for aFrom. */ while (!typeInfos.IsEmpty()) { RefPtr<ITypeInfo> curTypeInfo(Move(typeInfos.LastElement())); typeInfos.RemoveElementAt(typeInfos.Length() - 1); TYPEATTR* typeAttr = nullptr; HRESULT hr = curTypeInfo->GetTypeAttr(&typeAttr); if (FAILED(hr)) { break; } bool isFromParentVtable = IsVtableIndexFromParentInterface(typeAttr, aVtableIndexHint); WORD numParentInterfaces = typeAttr->cImplTypes; curTypeInfo->ReleaseTypeAttr(typeAttr); typeAttr = nullptr; if (!isFromParentVtable) { // The vtable index cannot belong to this interface (otherwise the IIDs // would already have matched and we would have returned true). Since we // now also know that the vtable index cannot possibly be contained inside // curTypeInfo's parent interface, there is no point searching any further // up the hierarchy from here. OTOH we still should check any remaining // entries that are still in the typeInfos array, so we continue. continue; } for (WORD i = 0; i < numParentInterfaces; ++i) { HREFTYPE refCookie; hr = curTypeInfo->GetRefTypeOfImplType(i, &refCookie); if (FAILED(hr)) { continue; } RefPtr<ITypeInfo> nextTypeInfo; hr = curTypeInfo->GetRefTypeInfo(refCookie, getter_AddRefs(nextTypeInfo)); if (FAILED(hr)) { continue; } hr = nextTypeInfo->GetTypeAttr(&typeAttr); if (FAILED(hr)) { continue; } IID nextIid = typeAttr->guid; nextTypeInfo->ReleaseTypeAttr(typeAttr); typeAttr = nullptr; if (nextIid == aFrom) { return true; } typeInfos.AppendElement(Move(nextTypeInfo)); } } return false; }