示例#1
0
size_t
ArenaAllocatorBase<TFreeListPolicy, ObjectAlignmentBitShiftArg, RequireObjectAlignment, MaxObjectSize>::
AllocatedSize()
{
    UpdateCacheBlock();
    return AllocatedSize(this->fullBlocks) + AllocatedSize(this->bigBlocks) + AllocatedSize(this->mallocBlocks);
}
GMPErr
GMPPlaneImpl::MaybeResize(int32_t aNewSize) {
  if (aNewSize <= AllocatedSize()) {
    return GMPNoErr;
  }

  if (!mHost) {
    return GMPGenericErr;
  }

  ipc::Shmem new_mem;
  if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData, aNewSize,
                                            ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
      !new_mem.get<uint8_t>()) {
    return GMPAllocErr;
  }

  if (mBuffer.IsReadable()) {
    memcpy(new_mem.get<uint8_t>(), Buffer(), mSize);
  }

  DestroyBuffer();

  mBuffer = new_mem;

  return GMPNoErr;
}
示例#3
0
// Special handing is needed around ReturnOutput as it spins the IPC message
// queue when creating an empty frame and can end up with reentrant calls into
// the class methods.
bool
WidevineVideoDecoder::ReturnOutput(WidevineVideoFrame& aCDMFrame)
{
  MOZ_ASSERT(mReturnOutputCallDepth >= 0);
  CounterHelper counterHelper(mReturnOutputCallDepth);
  mFrameAllocationQueue.push_back(Move(aCDMFrame));
  if (mReturnOutputCallDepth > 1) {
    // In a reentrant call.
    return true;
  }
  while (!mFrameAllocationQueue.empty()) {
    MOZ_ASSERT(mReturnOutputCallDepth == 1);
    // If we're at call level 1 a reset should not have been started. A
    // reset may be received during CreateEmptyFrame below, but we should not
    // be in a reset at this stage -- this would indicate receiving decode
    // messages before completing our reset, which we should not.
    MOZ_ASSERT(!mResetInProgress);
    WidevineVideoFrame currentCDMFrame = Move(mFrameAllocationQueue.front());
    mFrameAllocationQueue.pop_front();
    GMPVideoFrame* f = nullptr;
    auto err = mVideoHost->CreateFrame(kGMPI420VideoFrame, &f);
    if (GMP_FAILED(err) || !f) {
      Log("Failed to create i420 frame!\n");
      return false;
    }
    auto gmpFrame = static_cast<GMPVideoi420Frame*>(f);
    FrameDestroyerHelper frameDestroyerHelper(gmpFrame);
    Size size = currentCDMFrame.Size();
    const int32_t yStride = currentCDMFrame.Stride(VideoFrame::kYPlane);
    const int32_t uStride = currentCDMFrame.Stride(VideoFrame::kUPlane);
    const int32_t vStride = currentCDMFrame.Stride(VideoFrame::kVPlane);
    const int32_t halfHeight = size.height / 2;
    // This call can cause a shmem alloc, during this alloc other calls
    // may be made to this class and placed on the stack. ***WARNING***:
    // other IPC calls can happen during this call, resulting in calls
    // being made to the CDM. After this call state can have changed,
    // and should be reevaluated.
    err = gmpFrame->CreateEmptyFrame(size.width,
                                     size.height,
                                     yStride,
                                     uStride,
                                     vStride);
    // Assert possible reentrant calls or resets haven't altered level unexpectedly.
    MOZ_ASSERT(mReturnOutputCallDepth == 1);
    ENSURE_GMP_SUCCESS(err, false);

    // If a reset started we need to dump the current frame and complete the reset.
    if (mResetInProgress) {
      MOZ_ASSERT(mCDMWrapper);
      MOZ_ASSERT(mFrameAllocationQueue.empty());
      CompleteReset();
      return true;
    }

    err = gmpFrame->SetWidth(size.width);
    ENSURE_GMP_SUCCESS(err, false);

    err = gmpFrame->SetHeight(size.height);
    ENSURE_GMP_SUCCESS(err, false);

    Buffer* buffer = currentCDMFrame.FrameBuffer();
    uint8_t* outBuffer = gmpFrame->Buffer(kGMPYPlane);
    ENSURE_TRUE(outBuffer != nullptr, false);
    MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPYPlane) >= yStride*size.height);
    memcpy(outBuffer,
           buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kYPlane),
           yStride * size.height);

    outBuffer = gmpFrame->Buffer(kGMPUPlane);
    ENSURE_TRUE(outBuffer != nullptr, false);
    MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPUPlane) >= uStride * halfHeight);
    memcpy(outBuffer,
           buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kUPlane),
           uStride * halfHeight);

    outBuffer = gmpFrame->Buffer(kGMPVPlane);
    ENSURE_TRUE(outBuffer != nullptr, false);
    MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPVPlane) >= vStride * halfHeight);
    memcpy(outBuffer,
           buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kVPlane),
           vStride * halfHeight);

    gmpFrame->SetTimestamp(currentCDMFrame.Timestamp());

    auto d = mFrameDurations.find(currentCDMFrame.Timestamp());
    if (d != mFrameDurations.end()) {
      gmpFrame->SetDuration(d->second);
      mFrameDurations.erase(d);
    }

    // Forget frame so it's not deleted, call back taking ownership.
    frameDestroyerHelper.ForgetFrame();
    mCallback->Decoded(gmpFrame);
  }

  return true;
}