Adobe Premiere Pro導入插件開發遇到的一個問題


      最近在更新公司一款Premiere Pro CC導入插件的時候,遇到了一個神奇的現象。具體的現象是這樣的:我們的插件需要將一些私有的文件數據放到插件中,比如說當前活動的文件名。當插件中收到不同的selector時,我們能夠隨時獲取到這些私有數據進行操作。具體來說,我們是在收到imGetPrefs8這個selector時,進行設置的。回調函數代碼如下:

static prMALError
SDKGetPrefs8(
imStdParms			*stdParms,
imFileAccessRec8	*fileInfo8,
imGetPrefsRec		*prefsRec)
{
	//-----------------
	// The first time you are called (or if you've been Quieted or Closed)
	// you will get asked for prefs data.  First time called, return the
	// size of the buffer you want Premiere to store prefs for your plug-in.

	// Note: if canOpen is not set to kPrTrue, I'm not getting this selector. Why?
	// Answer: because this selector is associated directly with "hasSetup"

	if (prefsRec->prefsLength == 0) {
		prefsRec->prefsLength = sizeof(MediaSettings);
	}
	else {
		MediaSettings* settings = (MediaSettings*)prefsRec->prefs;
		//do not show dialog for the first time.
		if (fileInfo8->fileref != imInvalidHandleValue) {
			auto ctx = (FileContext*)(fileInfo8->fileref);
			if (!ctx || !ctx->media_source) {
				return malNoError;
			}  
			auto oldSettings = ctx->media_source->GetMediaSettings(); 
			settings->layout = oldSettings.layout;
			settings->lock_direction = oldSettings.lock_direction;
			settings->use_flowstate = oldSettings.use_flowstate;
			settings->media_case = oldSettings.media_case;
			settings->need_update = !settings->need_update;
			std::string currentFile = ctx->media_source->GetFilePath();
            ctx->media_source->ShowSettingsDialog(settings, currentFile);
			updateSettingFromFile(settings);
			ctx->media_source->UpdateSettings(settings);
		} 
		else {
			//init settings
			settings->use_flowstate = true;
		} 
	}
	return malNoError;
}

  根據Adobe官方提供的文檔說明,imGetPrefs8這個selector在文件導入的時候會連續發送兩次。第一次調用回調函數是為了獲取用戶私有數據緩存區的大小,Host程序會給我們分配這么大的一塊緩沖區。第二次調用的時候,這塊緩沖區已經分配好了。我們只要往這塊內存寫入私有用戶數據就行了。按道理說,這個過程非常清晰明了,不應該出現什么問題。可是在我實際調試的時候,彈窗獲取到用戶輸入后,並沒有馬上生效!那么,我是怎么判斷用戶輸入之后沒有生效呢?一般來說,如果用戶更改了什么設置,那么需要插件立即去調用SDKGetSourceVideo()函數的。

static
prMALError
SDKGetSourceVideo(
imStdParms *stdparms,
imFileRef    fileRef,
imSourceVideoRec *sourceVideoRec)
{
    int ret;

    ImporterLocalRec8H ldataH = reinterpret_cast<ImporterLocalRec8H>(sourceVideoRec->inPrivateData);
    ImporterLocalRec8Ptr localRecP = reinterpret_cast<ImporterLocalRec8Ptr>(*ldataH);

    // Get parameters for ReadFrameToBuffer()
    imFrameFormat* frameFormat = &sourceVideoRec->inFrameFormats[0];
    prRect theRect;
    if (frameFormat->inFrameWidth == 0 && frameFormat->inFrameHeight == 0)
    {
        frameFormat->inFrameWidth = localRecP->theFile.width;
        frameFormat->inFrameHeight = localRecP->theFile.height;
    }
    // Windows and MacOS have different definitions of Rects, so use the cross-platform prSetRect
    prSetRect(&theRect, 0, 0, frameFormat->inFrameWidth, frameFormat->inFrameHeight);
    localRecP->PPixCreatorSuite->CreatePPix(sourceVideoRec->outFrame, PrPPixBufferAccess_ReadWrite, frameFormat->inPixelFormat, &theRect);
    csSDK_int32 theFrame = static_cast<csSDK_int32>(sourceVideoRec->inFrameTime / (*ldataH)->theFile.frameRate);
    FileContext* ctx = (FileContext*)(localRecP)->fileRef;
    if (ctx == nullptr) {
        return imNoContent;
    }
    
    ...
    ...
    

    return imNoErr;
}

       這個函數負責根據當用的用戶設置來重新生成一幀數據傳遞給Host程序渲染,這樣用戶才能實時看到設置生效了。問題是,我們的用戶輸入改變之后,SDKGetSourceVideo()這個方法並沒有再次調用!那是什么原因導致的呢?難道是Premiere主程序有什么Bug?經過不斷調試才發現,這個鍋Premiere不能背啊!原因是,我在imGetPrefs8的回調函數中並沒有修改私有數據。也就是說,在上面的SDKGetPrefs8()方法中,我通過prefsRec獲取到用戶私有數據緩沖區之后,如果沒有修改過這塊內存區的數據的話,Premiere會認為不需要重新渲染畫面,也就不會再次調用SDKGetSourceVideo()方法了。

MediaSettings* settings = (MediaSettings*)prefsRec->prefs;

      這么看來,Premiere的這個機制還是有道理的。如果用戶私有數據沒有更改,很大可能是不需要重新渲染畫面的。這在某些計算頻繁的場景下可能能夠提供一定的性能提升。但是在文檔里面並沒有注明這一點。所以實際上,這個現象看起來像是一個鍋實際上並不是一個鍋……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM