/** * batch decideProfileConvert is the decision layer for a conversion profile * * @param BatchJob $parentJob * @param BatchJob $convertProfileJob * @param int $mediaInfoId * @return bool true if created all required conversions */ public static function decideProfileConvert(BatchJob $parentJob, BatchJob $convertProfileJob, $mediaInfoId = null) { KalturaLog::log("Conversion decision layer used for entry [" . $parentJob->getEntryId() . "]"); $convertProfileData = $convertProfileJob->getData(); $entryId = $convertProfileJob->getEntryId(); $entry = $convertProfileJob->getEntry(); if (!$entry) { throw new APIException(APIErrors::INVALID_ENTRY, $convertProfileJob, $entryId); } $profile = myPartnerUtils::getConversionProfile2ForEntry($entryId); if (!$profile) { $errDescription = "Conversion profile for entryId [{$entryId}] not found"; $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription, BatchJobType::CONVERT_PROFILE); kBatchManager::updateEntry($convertProfileJob, entryStatus::ERROR_CONVERTING); KalturaLog::err("No flavors created: {$errDescription}"); return false; } $originalFlavorAsset = flavorAssetPeer::retrieveOriginalByEntryId($entryId); if (is_null($originalFlavorAsset)) { $errDescription = 'Original flavor asset not found'; KalturaLog::err($errDescription); $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription, BatchJobType::CONVERT_PROFILE); kBatchManager::updateEntry($convertProfileJob, entryStatus::ERROR_CONVERTING); return false; } $shouldConvert = true; // gets the list of flavor params of the conversion profile $list = flavorParamsConversionProfilePeer::retrieveByConversionProfile($profile->getId()); if (!count($list)) { $errDescription = "No flavors match the profile id [{$profile->getId()}]"; KalturaLog::err($errDescription); $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription, BatchJobType::CONVERT_PROFILE); kBatchManager::updateEntry($convertProfileJob, entryStatus::ERROR_CONVERTING); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_DELETED); $originalFlavorAsset->setDeletedAt(time()); $originalFlavorAsset->save(); return false; } $mediaInfo = null; if ($mediaInfoId) { $mediaInfo = mediaInfoPeer::retrieveByPK($mediaInfoId); } if ($profile->getCreationMode() == ConversionProfile2::CONVERSION_PROFILE_2_CREATION_MODE_AUTOMATIC_BYPASS_FLV) { KalturaLog::log("The profile created from old conversion profile with bypass flv"); $isFlv = false; if ($mediaInfo) { $isFlv = KDLWrap::CDLIsFLV($mediaInfo); } if ($isFlv && $originalFlavorAsset->hasTag(flavorParams::TAG_MBR)) { KalturaLog::log("The source is mbr and flv, conversion will be bypassed"); $shouldConvert = false; } else { KalturaLog::log("The source is NOT mbr or flv, conversion will NOT be bypassed"); } } // gets the ids of the flavor params $flavorsIds = array(); $conversionProfileFlavorParams = array(); foreach ($list as $flavorParamsConversionProfile) { $flavorsId = $flavorParamsConversionProfile->getFlavorParamsId(); $flavorsIds[] = $flavorsId; $conversionProfileFlavorParams[$flavorsId] = $flavorParamsConversionProfile; } $dynamicFlavorAttributes = $entry->getDynamicFlavorAttributes(); $sourceFlavor = null; $flavors = flavorParamsPeer::retrieveByPKs($flavorsIds); foreach ($flavors as $index => $flavor) { if (isset($dynamicFlavorAttributes[$flavor->getId()])) { foreach ($dynamicFlavorAttributes[$flavor->getId()] as $attributeName => $attributeValue) { $flavor->setDynamicAttribute($attributeName, $attributeValue); } } if ($flavor->hasTag(flavorParams::TAG_SOURCE)) { $sourceFlavor = $flavor; unset($flavors[$index]); } } KalturaLog::log(count($flavors) . " destination flavors found for this profile[" . $profile->getId() . "]"); if (!$sourceFlavor) { KalturaLog::log("Source flavor params not found"); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_TEMP); $originalFlavorAsset->save(); } elseif ($shouldConvert) { KalturaLog::log("Source flavor params [" . $sourceFlavor->getId() . "] found"); $originalFlavorAsset->setFlavorParamsId($sourceFlavor->getId()); if ($sourceFlavor->getOperators() || $sourceFlavor->getConversionEngines()) { KalturaLog::log("Source flavor asset requires conversion"); $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $errDescription = null; $sourceFlavorOutput = self::validateFlavorAndMediaInfo($sourceFlavor, $mediaInfo, $errDescription); // save flavor params $sourceFlavorOutput->setPartnerId($sourceFlavorOutput->getPartnerId()); $sourceFlavorOutput->setEntryId($entryId); $sourceFlavorOutput->setFlavorAssetId($originalFlavorAsset->getId()); $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } $errDescription = kBusinessConvertDL::parseFlavorDescription($sourceFlavorOutput); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } // decided by the business logic layer if ($sourceFlavorOutput->_create_anyway) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] selected to be created anyway"); } else { if (!$sourceFlavorOutput->IsValid()) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is invalid"); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR); $originalFlavorAsset->save(); $errDescription = "Source flavor could not be converted"; KalturaLog::err($errDescription); $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription, BatchJobType::CONVERT_PROFILE); kBatchManager::updateEntry($convertProfileJob, entryStatus::ERROR_CONVERTING); return false; } if ($sourceFlavorOutput->_force) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is forced"); } elseif ($sourceFlavorOutput->_isNonComply) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is none-comply"); } else { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is valid"); } } $originalFlavorAsset->incrementVersion(); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_QUEUED); $originalFlavorAsset->addTags($sourceFlavor->getTagsArray()); $originalFlavorAsset->setFileExt($sourceFlavorOutput->getFileExt()); $originalFlavorAsset->save(); // save flavor params $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); kJobsManager::addFlavorConvertJob($srcSyncKey, $sourceFlavorOutput, $originalFlavorAsset->getId(), $mediaInfoId, $parentJob); return false; } $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_READY); $originalFlavorAsset->save(); $entry->addFlavorParamsId($sourceFlavor->getId()); $entry->save(); kFlowHelper::generateThumbnailsFromFlavor($parentJob->getEntryId(), $parentJob); } if (!count($flavors)) { $shouldConvert = false; } if (!$shouldConvert) { self::bypassConversion($originalFlavorAsset, $entry, $convertProfileJob); return true; } return self::decideProfileFlavorsConvert($parentJob, $convertProfileJob, $flavors, $conversionProfileFlavorParams, $mediaInfo); }
function calculateEstimatedEffort(BatchJob $batchJob) { $mediaInfo = mediaInfoPeer::retrieveByPK($this->getMediaInfoId()); if (is_null($mediaInfo)) { $sumEffort = 0; $fileSyncs = $this->getSrcFileSyncs(); foreach ($fileSyncs as $fileSync) { $fileSize = filesize($fileSync->getFileSyncLocalPath()); if ($fileSize !== False) { $sumEffort += $fileSize; } } if ($sumEffort != 0) { return $sumEffort; } return self::MAX_ESTIMATED_EFFORT; } else { return max($mediaInfo->getVideoDuration(), $mediaInfo->getAudioDuration(), $mediaInfo->getContainerDuration()); } }
/** * @param BatchJob $dbBatchJob * @param kExtractMediaJobData $data * @param BatchJob $twinJob * @return BatchJob */ public static function handleExtractMediaClosed(BatchJob $dbBatchJob, kExtractMediaJobData $data, BatchJob $twinJob = null) { KalturaLog::debug("Extract media closed"); if ($dbBatchJob->getAbort()) { return $dbBatchJob; } $rootBatchJob = $dbBatchJob->getRootJob(); if (!$rootBatchJob) { return $dbBatchJob; } if ($twinJob) { // copy media info $twinData = $twinJob->getData(); if ($twinData->getMediaInfoId()) { $twinMediaInfo = mediaInfoPeer::retrieveByPK($twinData->getMediaInfoId()); if ($twinMediaInfo) { $mediaInfo = $twinMediaInfo->copy(); $mediaInfo->setFlavorAssetId($data->getFlavorAssetId()); $mediaInfo = kBatchManager::addMediaInfo($mediaInfo); $data->setMediaInfoId($mediaInfo->getId()); $dbBatchJob->setData($data); $dbBatchJob->save(); } } } if ($dbBatchJob->getStatus() == BatchJob::BATCHJOB_STATUS_FINISHED) { $entry = $dbBatchJob->getEntry(); if ($entry->getStatus() < entryStatus::READY) { kBatchManager::updateEntry($dbBatchJob, entryStatus::PRECONVERT); } } switch ($dbBatchJob->getJobSubType()) { case mediaInfo::ASSET_TYPE_ENTRY_INPUT: if ($rootBatchJob->getJobType() == BatchJobType::CONVERT_PROFILE) { $conversionsCreated = kBusinessPreConvertDL::decideProfileConvert($dbBatchJob, $rootBatchJob, $data->getMediaInfoId()); if ($conversionsCreated) { // handle the source flavor as if it was converted, makes the entry ready according to ready behavior rules $currentFlavorAsset = flavorAssetPeer::retrieveById($data->getFlavorAssetId()); if ($currentFlavorAsset) { $dbBatchJob = kBusinessPostConvertDL::handleConvertFinished($dbBatchJob, $currentFlavorAsset); } } } break; case mediaInfo::ASSET_TYPE_FLAVOR_INPUT: if ($rootBatchJob->getJobType() == BatchJobType::REMOTE_CONVERT) { $remoteConvertData = $rootBatchJob->getData(); $errDescription = null; $syncKey = null; // TODO - how to get or create the sync key? $newConvertJob = kBusinessPreConvertDL::decideFlavorConvert($syncKey, $remoteConvertData->getFlavorParamsOutputId(), $errDescription, $remoteConvertData->getMediaInfoId(), $dbBatchJob); if (!$newConvertJob) { kJobsManager::failBatchJob($rootBatchJob); } } break; default: // currently do nothing break; } return $dbBatchJob; }
/** * batch decideProfileConvert is the decision layer for a conversion profile * * @param BatchJob $parentJob * @param BatchJob $convertProfileJob * @param int $mediaInfoId * @return bool true if created all required conversions */ public static function decideProfileConvert(BatchJob $parentJob, BatchJob $convertProfileJob, $mediaInfoId = null) { KalturaLog::log("Conversion decision layer used for entry [" . $parentJob->getEntryId() . "]"); $convertProfileData = $convertProfileJob->getData(); $entryId = $convertProfileJob->getEntryId(); $entry = $convertProfileJob->getEntry(); if (!$entry) { throw new APIException(APIErrors::INVALID_ENTRY, $convertProfileJob, $entryId); } $profile = myPartnerUtils::getConversionProfile2ForEntry($entryId); if (!$profile) { $errDescription = "Conversion profile for entryId [{$entryId}] not found"; self::setError($errDescription, $convertProfileJob, BatchJobType::CONVERT_PROFILE, $convertProfileJob->getEntryId()); return false; } $originalFlavorAsset = assetPeer::retrieveOriginalByEntryId($entryId); if (is_null($originalFlavorAsset)) { $errDescription = 'Original flavor asset not found'; self::setError($errDescription, $convertProfileJob, BatchJobType::CONVERT_PROFILE, $convertProfileJob->getEntryId()); return false; } // gets the list of flavor params of the conversion profile $list = flavorParamsConversionProfilePeer::retrieveByConversionProfile($profile->getId()); if (!count($list)) { $errDescription = "No flavors match the profile id [{$profile->getId()}]"; self::setError($errDescription, $convertProfileJob, BatchJobType::CONVERT_PROFILE, $convertProfileJob->getEntryId()); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_DELETED); $originalFlavorAsset->setDeletedAt(time()); $originalFlavorAsset->save(); return false; } $mediaInfo = null; if ($mediaInfoId) { $mediaInfo = mediaInfoPeer::retrieveByPK($mediaInfoId); } $shouldConvert = self::shouldConvertProfileFlavors($profile, $mediaInfo, $originalFlavorAsset); // gets the ids of the flavor params $flavorsIds = array(); $conversionProfileFlavorParams = array(); foreach ($list as $flavorParamsConversionProfile) { $flavorsId = $flavorParamsConversionProfile->getFlavorParamsId(); $flavorsIds[] = $flavorsId; $conversionProfileFlavorParams[$flavorsId] = $flavorParamsConversionProfile; } KalturaLog::info("Flavors in conversion profile [" . implode(',', $flavorsIds) . "]"); $sourceFlavor = null; $flavors = assetParamsPeer::retrieveFlavorsByPKs($flavorsIds); $ingestedNeeded = self::checkConvertProfileParams($flavors, $conversionProfileFlavorParams, $entry, $sourceFlavor); KalturaLog::log(count($flavors) . " destination flavors found for this profile[" . $profile->getId() . "]"); if (!$sourceFlavor) { KalturaLog::log("Source flavor params not found"); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_TEMP); $originalFlavorAsset->save(); /* * Check for 'auto-intermediate-source */ $res = self::decideSourceFlavorConvert($entryId, null, $originalFlavorAsset, $profile->getId(), $flavors, $mediaInfo, $parentJob, $convertProfileJob); if (!$res) { $originalFlavorAsset->incrementInterFlowCount(); $originalFlavorAsset->save(); return false; } $originalFlavorAsset->removeInterFlowCount(); $originalFlavorAsset->save(); } elseif ($shouldConvert) { KalturaLog::log("Source flavor params [" . $sourceFlavor->getId() . "] found"); $originalFlavorAsset->setFlavorParamsId($sourceFlavor->getId()); $res = self::decideSourceFlavorConvert($entryId, $sourceFlavor, $originalFlavorAsset, $profile->getId(), $flavors, $mediaInfo, $parentJob, $convertProfileJob); if (!$res) { $originalFlavorAsset->incrementInterFlowCount(); $originalFlavorAsset->save(); return false; } $originalFlavorAsset->removeInterFlowCount(); $originalFlavorAsset->setStatusLocalReady(); $originalFlavorAsset->save(); $entry->save(); kFlowHelper::generateThumbnailsFromFlavor($parentJob->getEntryId(), $parentJob); } if (!count($flavors)) { $shouldConvert = false; } if (!$shouldConvert) { if ($ingestedNeeded) { kJobsManager::updateBatchJob($convertProfileJob, BatchJob::BATCHJOB_STATUS_FINISHED); return false; } else { self::bypassConversion($originalFlavorAsset, $entry, $convertProfileJob); return true; } } try { return self::decideProfileFlavorsConvert($parentJob, $convertProfileJob, $flavors, $conversionProfileFlavorParams, $profile->getId(), $mediaInfo); } catch (Exception $e) { $code = $e->getCode(); if ($code == KDLErrors::SanityInvalidFrameDim || $code == KDLErrors::NoValidMediaStream) { throw $e; } } }
/** * addFlavorConvertJob adds a single flavor conversion * * @param FileSyncKey $srcSyncKey * @param flavorParamsOutput $flavor * @param int $flavorAssetId * @param int $conversionProfileId * @param int $mediaInfoId * @param BatchJob $parentJob * @param int $lastEngineType * @param bool $sameRoot * @return BatchJob */ public static function addFlavorConvertJob(array $srcSyncKeys, flavorParamsOutput $flavor, $flavorAssetId, $conversionProfileId = null, $mediaInfoId = null, BatchJob $parentJob = null, $lastEngineType = null, $sameRoot = true, $priority = 0) { KalturaLog::debug('Add convert job for [' . $flavorAssetId . ']'); $flavorAsset = assetPeer::retrieveById($flavorAssetId); if (!$flavorAsset) { KalturaLog::err("No flavor asset found for id [{$flavorAssetId}]"); return null; } $partner = PartnerPeer::retrieveByPK($flavorAsset->getPartnerId()); $srcFileSyncs = array(); $waitForImportComplete = false; foreach ($srcSyncKeys as $srcSyncKey) { $srcFileSyncDescriptor = new kSourceFileSyncDescriptor(); $addImportJob = false; $fileSync = self::getFileSyncForKey($srcSyncKey, $flavor, $flavorAsset, $partner, $addImportJob); if (!$fileSync) { return null; } $srcFlavorAsset = assetPeer::retrieveById($srcSyncKey->getObjectId()); if ($addImportJob) { KalturaLog::debug("Creates import job for remote file sync"); $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_WAIT_FOR_CONVERT); $flavorAsset->setDescription("Source file sync is importing: {$srcSyncKey}"); $flavorAsset->save(); $url = $fileSync->getExternalUrl($flavorAsset->getEntryId()); kJobsManager::addImportJob($parentJob, $flavorAsset->getEntryId(), $partner->getId(), $url, $srcFlavorAsset, null, null, true); $waitForImportComplete = true; } else { if ($flavor->getSourceRemoteStorageProfileId() == StorageProfile::STORAGE_KALTURA_DC) { if ($fileSync->getFileType() != FileSync::FILE_SYNC_FILE_TYPE_URL) { $srcFileSyncDescriptor->setFileSyncLocalPath($fileSync->getFullPath()); } } else { $srcFileSyncDescriptor->setFileSyncLocalPath($fileSync->getFilePath()); } $srcFileSyncDescriptor->setFileSyncRemoteUrl($fileSync->getExternalUrl($flavorAsset->getEntryId())); $srcFileSyncDescriptor->setAssetId($srcSyncKey->getObjectId()); $srcFileSyncDescriptor->setAssetParamsId($srcFlavorAsset->getFlavorParamsId()); $srcFileSyncDescriptor->setFileSyncObjectSubType($srcSyncKey->getObjectSubType()); $srcFileSyncs[] = $srcFileSyncDescriptor; } } if ($waitForImportComplete) { return; } // creates convert data $convertData = new kConvertJobData(); $convertData->setSrcFileSyncs($srcFileSyncs); $convertData->setMediaInfoId($mediaInfoId); $convertData->setFlavorParamsOutputId($flavor->getId()); $convertData->setFlavorAssetId($flavorAssetId); $convertData->setConversionProfileId($conversionProfileId); $convertData->setPriority($priority); $dbCurrentConversionEngine = self::getNextConversionEngine($flavor, $parentJob, $lastEngineType, $convertData); if (!$dbCurrentConversionEngine) { return null; } // creats a child convert job if ($parentJob) { $dbConvertFlavorJob = $parentJob->createChild(BatchJobType::CONVERT, $dbCurrentConversionEngine, $sameRoot); KalturaLog::log("Created from parent job"); } else { $dbConvertFlavorJob = new BatchJob(); $dbConvertFlavorJob->setPartnerId($flavor->getPartnerId()); $dbConvertFlavorJob->setJobType(BatchJobType::CONVERT); $dbConvertFlavorJob->setJobSubType($dbCurrentConversionEngine); KalturaLog::log("Created from flavor convert job"); } $dbConvertFlavorJob->setEntryId($flavor->getEntryId()); KalturaLog::log("Job created with entry id [" . $dbConvertFlavorJob->getEntryId() . "]"); $mediaInfo = mediaInfoPeer::retrieveByPK($mediaInfoId); if ($mediaInfo === NULL) { // in case we don't know the estimatted info, we will set it to a big number. $estimatedEffort = kJobData::MAX_ESTIMATED_EFFORT; } else { $estimatedEffort = max($mediaInfo->getVideoDuration(), $mediaInfo->getAudioDuration(), $mediaInfo->getContainerDuration()); } $dbConvertFlavorJob->setObjectId($flavorAssetId); $dbConvertFlavorJob->setObjectType(BatchJobObjectType::ASSET); return kJobsManager::addJob($dbConvertFlavorJob, $convertData, BatchJobType::CONVERT, $dbCurrentConversionEngine); }
/** * @param BatchJob $dbBatchJob * @param kExtractMediaJobData $data * @param BatchJob $twinJob * @return BatchJob */ public static function handleExtractMediaClosed(BatchJob $dbBatchJob, kExtractMediaJobData $data, BatchJob $twinJob = null) { KalturaLog::debug("Extract media closed"); if ($dbBatchJob->getAbort()) { return $dbBatchJob; } $rootBatchJob = $dbBatchJob->getRootJob(); if (!$rootBatchJob) { return $dbBatchJob; } if ($twinJob) { // copy media info $twinData = $twinJob->getData(); if ($twinData->getMediaInfoId()) { $twinMediaInfo = mediaInfoPeer::retrieveByPK($twinData->getMediaInfoId()); if ($twinMediaInfo) { $mediaInfo = $twinMediaInfo->copy(); $mediaInfo->setFlavorAssetId($data->getFlavorAssetId()); $mediaInfo = kBatchManager::addMediaInfo($mediaInfo); $data->setMediaInfoId($mediaInfo->getId()); $dbBatchJob->setData($data); $dbBatchJob->save(); } } } if ($dbBatchJob->getStatus() == BatchJob::BATCHJOB_STATUS_FINISHED) { $entry = entryPeer::retrieveByPKNoFilter($dbBatchJob->getEntryId()); if ($entry->getStatus() != entryStatus::READY && $entry->getStatus() != entryStatus::DELETED) { kBatchManager::updateEntry($dbBatchJob->getEntryId(), entryStatus::PRECONVERT); } } if ($rootBatchJob->getJobType() == BatchJobType::CONVERT_PROFILE) { kBusinessPreConvertDL::decideProfileConvert($dbBatchJob, $rootBatchJob, $data->getMediaInfoId()); // handle the source flavor as if it was converted, makes the entry ready according to ready behavior rules $currentFlavorAsset = assetPeer::retrieveById($data->getFlavorAssetId()); if ($currentFlavorAsset && $currentFlavorAsset->getStatus() == asset::FLAVOR_ASSET_STATUS_READY) { $dbBatchJob = kBusinessPostConvertDL::handleConvertFinished($dbBatchJob, $currentFlavorAsset); } } return $dbBatchJob; }