void WidevineVideoDecoder::Drain() { Log("WidevineVideoDecoder::Drain()"); if (mReturnOutputCallDepth > 0) { Log("Drain call is reentrant, postponing drain"); mDrainPending = true; return; } Status rv = kSuccess; while (rv == kSuccess) { WidevineVideoFrame frame; InputBuffer sample; Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); Log("WidevineVideoDecoder::Drain(); DecryptAndDecodeFrame() rv=%d", rv); if (frame.Format() == kUnknownVideoFormat) { break; } if (rv == kSuccess) { if (!ReturnOutput(frame)) { Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); } } } // Shouldn't be reset while draining. MOZ_ASSERT(!mResetInProgress); CDM()->ResetDecoder(kStreamTypeVideo); mDrainPending = false; mCallback->DrainComplete(); }
void WidevineVideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings, const uint8_t* aCodecSpecific, uint32_t aCodecSpecificLength, GMPVideoDecoderCallback* aCallback, int32_t aCoreCount) { mCallback = aCallback; VideoDecoderConfig config; config.codec = VideoDecoderConfig::kCodecH264; // TODO: others. const GMPVideoCodecH264* h264 = (const GMPVideoCodecH264*)(aCodecSpecific); config.profile = ToCDMH264Profile(h264->mAVCC.mProfile); config.format = kYv12; config.coded_size = Size(aCodecSettings.mWidth, aCodecSettings.mHeight); mExtraData->AppendElements(aCodecSpecific + 1, aCodecSpecificLength); config.extra_data = mExtraData->Elements(); config.extra_data_size = mExtraData->Length(); Status rv = CDM()->InitializeVideoDecoder(config); if (rv != kSuccess) { mCallback->Error(ToGMPErr(rv)); return; } Log("WidevineVideoDecoder::InitDecode() rv=%d", rv); mAnnexB = mp4_demuxer::AnnexB::ConvertExtraDataToAnnexB(mExtraData); }
void WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken, uint32_t aPromiseId, const char* aInitDataType, uint32_t aInitDataTypeSize, const uint8_t* aInitData, uint32_t aInitDataSize, GMPSessionType aSessionType) { Log("Decryptor::CreateSession(token=%d, pid=%d)", aCreateSessionToken, aPromiseId); InitDataType initDataType; if (!strcmp(aInitDataType, "cenc")) { initDataType = kCenc; } else if (!strcmp(aInitDataType, "webm")) { initDataType = kWebM; } else if (!strcmp(aInitDataType, "keyids")) { initDataType = kKeyIds; } else { // Invalid init data type const char* errorMsg = "Invalid init data type when creating session."; OnRejectPromise(aPromiseId, kNotSupportedError, 0, errorMsg, sizeof(errorMsg)); return; } mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken; CDM()->CreateSessionAndGenerateRequest(aPromiseId, ToCDMSessionType(aSessionType), initDataType, aInitData, aInitDataSize); }
void WidevineDecryptor::CloseSession(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdLength) { Log("Decryptor::CloseSession(pid=%d, session=%s)", aPromiseId, aSessionId); CDM()->CloseSession(aPromiseId, aSessionId, aSessionIdLength); }
void WidevineDecryptor::SetServerCertificate(uint32_t aPromiseId, const uint8_t* aServerCert, uint32_t aServerCertSize) { Log("Decryptor::SetServerCertificate()"); CDM()->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize); }
void WidevineDecryptor::RemoveSession(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdLength) { Log("Decryptor::RemoveSession(%s)", aSessionId); CDM()->RemoveSession(aPromiseId, aSessionId, aSessionIdLength); }
void WidevineDecryptor::Init(GMPDecryptorCallback* aCallback, bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired) { Log("WidevineDecryptor::Init() this=%p distinctiveId=%d persistentState=%d", this, aDistinctiveIdentifierRequired, aPersistentStateRequired); MOZ_ASSERT(aCallback); mCallback = aCallback; MOZ_ASSERT(mCDM); mDistinctiveIdentifierRequired = aDistinctiveIdentifierRequired; mPersistentStateRequired = aPersistentStateRequired; if (CDM()) { CDM()->Initialize(aDistinctiveIdentifierRequired, aPersistentStateRequired); } }
void WidevineDecryptor::LoadSession(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdLength) { Log("Decryptor::LoadSession(pid=%d, %s)", aPromiseId, aSessionId); // TODO: session type?? CDM()->LoadSession(aPromiseId, kPersistentLicense, aSessionId, aSessionIdLength); }
void WidevineDecryptor::UpdateSession(uint32_t aPromiseId, const char* aSessionId, uint32_t aSessionIdLength, const uint8_t* aResponse, uint32_t aResponseSize) { Log("Decryptor::UpdateSession(pid=%d, session=%s)", aPromiseId, aSessionId); CDM()->UpdateSession(aPromiseId, aSessionId, aSessionIdLength, aResponse, aResponseSize); }
void WidevineVideoDecoder::DecodingComplete() { Log("WidevineVideoDecoder::DecodingComplete()"); if (mCDMWrapper) { CDM()->DeinitializeDecoder(kStreamTypeVideo); mCDMWrapper = nullptr; } // Release that corresponds to AddRef() in constructor. Release(); }
void WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken, uint32_t aPromiseId, const char* aInitDataType, uint32_t aInitDataTypeSize, const uint8_t* aInitData, uint32_t aInitDataSize, GMPSessionType aSessionType) { Log("Decryptor::CreateSession(token=%d, pid=%d)", aCreateSessionToken, aPromiseId); MOZ_ASSERT(!strcmp(aInitDataType, "cenc")); mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken; CDM()->CreateSessionAndGenerateRequest(aPromiseId, ToCDMSessionType(aSessionType), kCenc, aInitData, aInitDataSize); }
void WidevineVideoDecoder::Reset() { Log("WidevineVideoDecoder::Reset() mSentInput=%d", mSentInput); // We shouldn't reset if a drain is pending. MOZ_ASSERT(!mDrainPending); mResetInProgress = true; if (mSentInput) { CDM()->ResetDecoder(kStreamTypeVideo); } // Remove queued frames, but do not reset mReturnOutputCallDepth, let the // ReturnOutput calls unwind and decrement the counter as needed. mFrameAllocationQueue.clear(); mFrameDurations.clear(); // Only if no ReturnOutput calls are in progress can we complete, otherwise // ReturnOutput needs to finalize the reset. if (mReturnOutputCallDepth == 0) { CompleteReset(); } }
void WidevineDecryptor::Decrypt(GMPBuffer* aBuffer, GMPEncryptedBufferMetadata* aMetadata) { if (!mCallback) { Log("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this); return; } const GMPEncryptedBufferMetadata* crypto = aMetadata; InputBuffer sample; nsTArray<SubsampleEntry> subsamples; InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples); WidevineDecryptedBlock decrypted; Status rv = CDM()->Decrypt(sample, &decrypted); Log("Decryptor::Decrypt(timestamp=%lld) rv=%d sz=%d", sample.timestamp, rv, decrypted.DecryptedBuffer()->Size()); if (rv == kSuccess) { aBuffer->Resize(decrypted.DecryptedBuffer()->Size()); memcpy(aBuffer->Data(), decrypted.DecryptedBuffer()->Data(), decrypted.DecryptedBuffer()->Size()); } mCallback->Decrypted(aBuffer, ToGMPErr(rv)); }
void WidevineVideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame, bool aMissingFrames, const uint8_t* aCodecSpecificInfo, uint32_t aCodecSpecificInfoLength, int64_t aRenderTimeMs) { // We should not be given new input if a drain has been initiated MOZ_ASSERT(!mDrainPending); // We may not get the same out of the CDM decoder as we put in, and there // may be some latency, i.e. we may need to input (say) 30 frames before // we receive output. So we need to store the durations of the frames input, // and retrieve them on output. mFrameDurations[aInputFrame->TimeStamp()] = aInputFrame->Duration(); mSentInput = true; InputBuffer sample; RefPtr<MediaRawData> raw(new MediaRawData(aInputFrame->Buffer(), aInputFrame->Size())); raw->mExtraData = mExtraData; raw->mKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame); // Convert input from AVCC, which GMPAPI passes in, to AnnexB, which // Chromium uses internally. mp4_demuxer::AnnexB::ConvertSampleToAnnexB(raw); const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData(); nsTArray<SubsampleEntry> subsamples; InitInputBuffer(crypto, aInputFrame->TimeStamp(), raw->Data(), raw->Size(), sample, subsamples); // For keyframes, ConvertSampleToAnnexB will stick the AnnexB extra data // at the start of the input. So we need to account for that as clear data // in the subsamples. if (raw->mKeyframe && !subsamples.IsEmpty()) { subsamples[0].clear_bytes += mAnnexB->Length(); } WidevineVideoFrame frame; Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); Log("WidevineVideoDecoder::Decode(timestamp=%lld) rv=%d", sample.timestamp, rv); // Destroy frame, so that the shmem is now free to be used to return // output to the Gecko process. aInputFrame->Destroy(); aInputFrame = nullptr; if (rv == kSuccess) { if (!ReturnOutput(frame)) { Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); mCallback->Error(GMPDecodeErr); return; } // A reset should only be started at most at level mReturnOutputCallDepth 1, // and if it's started it should be finished by that call by the time // the it returns, so it should always be false by this point. MOZ_ASSERT(!mResetInProgress); // Only request more data if we don't have pending samples. if (mFrameAllocationQueue.empty()) { MOZ_ASSERT(mCDMWrapper); mCallback->InputDataExhausted(); } } else if (rv == kNeedMoreData) { MOZ_ASSERT(mCDMWrapper); mCallback->InputDataExhausted(); } else { mCallback->Error(ToGMPErr(rv)); } // Finish a drain if pending and we have no pending ReturnOutput calls on the stack. if (mDrainPending && mReturnOutputCallDepth == 0) { Drain(); } }
void CLightSet::RunLightPrep(IplImage* src,IplImage* dest) { int M,N; M=0; N=0; if (src->roi) { M = src->roi->width; N = src->roi->height; } else { M = src->width; N = src->height; } CvMat *matD; // create mat for meshgrid frequency matrices matD = cvCreateMat(M,N,CV_32FC1); CDM(M,N,matD); CvMat *matH; matH = cvCreateMat(M,N,CV_32FC1); // mat for lowpass filter float D0 = 10.0; float rH,rL,c; rH = 2.0; rL = 0.5; c = 1.0; lpfilter(matD,matH,D0,rH,rL,c); IplImage *srcshift; // shift center srcshift = cvCloneImage(src); cvShiftDFT(srcshift,srcshift); IplImage *log, *temp; log = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,1); temp = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,1); cvCvtScale(srcshift,temp,1.0,0); cvLog(temp,log); cvCvtScale(log,log,-1.0,0); CvMat *Fourier; Fourier = cvCreateMat( M, N, CV_32FC2 ); fft2(log,Fourier); IplImage* image_im; image_im = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,1); cvSplit(Fourier,dest,image_im,0,0); cvMul(dest,matH,dest); cvMul(image_im,matH,image_im); IplImage *dst; dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,2); cvMerge(dest,image_im,0,0,dst); cvDFT(dst,dst,CV_DXT_INV_SCALE); cvExp(dst,dst); cvZero(dest); cvZero(image_im); cvSplit(dst,dest,image_im,0,0); //使得图像按照原来的顺序显示 cvShiftDFT(dest,dest); double max,min; // normalize cvMinMaxLoc(dest,&min,&max,NULL,NULL); cvReleaseImage(&image_im); cvReleaseImage(&srcshift); cvReleaseImage(&dst); cvReleaseImage(&log); cvReleaseImage(&temp); cvReleaseMat(&matD); cvReleaseMat(&matH); }