专栏首页24K纯开源Premiere&After Effects的实时预览插件开发

Premiere&After Effects的实时预览插件开发

一、介绍

        Adobe Premiere和After Effects在影视编辑、渲染领域已经得到广泛应用。全景视频在相应工具拼接好后也可以导入Premiere/After Effects后也可进行剪辑、渲染。但由于全景视频存在畸变、视角、拼接技术等因素,即使平铺时也无法很好的查看场景细节。这对于视频剪辑带来一定的不变。如果能一边剪辑视频一边在全景播放器中查看效果,那便再好不过了。gopro旗下的Kolor eye视频播放器就实现了这样的一种功能。实际上这个功能做起来并不难,其实就是基于Adobe Premiere Transmitter插件实现的。当然,Kolor Eye播放器插件也不例外。

二、插件开发

        下面就聊聊如何开发吧。Adobe Premiere插件开发使用C++语言,并且依赖官方提供的开发包。因此在正式动手前需要下载好Adobe Plugin SDK。在SDK中的Projects目录下即可打开Demo工程:

        在TransmitterPlugin.h文件中,我们先把插件名称修改成自己需要的名字:

#define    PLUGIN_DISPLAY_NAME    L"Demo Preview"

  其他地方保持原样。然后打开对应的cpp文件进行修改。这里要实现两个功能:

  • 在恰当的时候启动外部全景播放器。
  • 将视频流持续转发给外部全景播放器。

        那么应该怎么做呢。TransmitterPlugin.cpp文件中主要注意两个方法即可:StartPlaybackClock()PushVideo()方法。StartPlaybackClock()方法在即将播放视频的时候调用,我们选择在这个时候启动外部播放器是再自然不过了。这里通过进程枚举来判断外部播放器是否启动了。如果安装了外部播放器且没有启动,则启动播放器;否则直接利用已启动的播放器进行播放。

tmResult TransmitInstance::StartPlaybackClock(
    const tmStdParms* inStdParms,
    const tmInstance* inInstance,
    const tmPlaybackClock* inClock)
{
    ...
    frameTimeInSeconds = (float)inClock->inStartTime / mTicksPerSecond;
    // If not yet playing, and called to play,
    // then register our UpdateClock function that calls the audio callback asynchronously during playback
    // Note that StartPlaybackClock can be called multiple times without a StopPlaybackClock,
    // for example if changing playback speed in the timeline.
    // If already playing, we the callbackContext doesn't change, and we let the current clock continue.
    if (!mPlaying && inClock->inPlayMode == playmode_Playing)
    {
        mPlaying = kPrTrue;
        if (installFlag && !FindProcessByName(wcsrchr(mLocation, L'/') + 1))
        {
            HINSTANCE hInstance;
            hInstance = ShellExecute(NULL, TEXT("open"), mLocation, TEXT("previewplugin 2048 1024"), NULL, SW_SHOWNORMAL);
            LOGINFO(L"ShellExecute returns %d", (int)hInstance);
        }
        // Initialize the ClockInstanceData that the UpdateClock function will need
        // We allocate the data here, and the data will be disposed at the end of the UpdateClock function
       ...
    }
    return tmResult_Success;
}

  而PushVideo()根据字面意思就可以知道,是用来转发视频帧数据的,这也是为啥工程名叫Transmitter的原因。接下来,如何将视频帧数据传递给外部播放器呢?这里选择了Windows平台的内存共享技术。

tmResult TransmitInstance::PushVideo(
	const tmStdParms* inStdParms,
	const tmInstance* inInstance,
	const tmPushVideo* inPushVideo)
{
    ....
	frameTimeInSeconds = (float)inPushVideo->inTime / mTicksPerSecond;
	mSuites.PPixSuite->GetBounds(inPushVideo->inFrames[0].inFrame, &frameBounds);
	videoSize[0] = (frameBounds.right - frameBounds.left);
	videoSize[1] = (frameBounds.bottom - frameBounds.top);
	// Since we have ARGB color space mode.
	mSuites.PPixSuite->GetPixelAspectRatio(inPushVideo->inFrames[0].inFrame, &parNum, &parDen);
	mSuites.PPixSuite->GetPixelFormat(inPushVideo->inFrames[0].inFrame, &pixelFormat);

	mSuites.SequenceInfoSuite->GetZeroPoint(inInstance->inTimelineID, &zeroPointTime);
	mSuites.SequenceInfoSuite->GetTimecodeDropFrame(inInstance->inTimelineID, &dropFrame);
	mSuites.PPixSuite->GetPixels(inPushVideo->inFrames[0].inFrame, PrPPixBufferAccess_ReadWrite, &pixelsBuffer);

	if (videoSize[0] <= 0 || videoSize[1] <= 0)
	{
		// Dispose of the PPix(es) when done!
		for (int i = 0; i < inPushVideo->inFrameCount; i++)
		{
			mSuites.PPixSuite->Dispose(inPushVideo->inFrames[i].inFrame);
		}

		return tmResult_Success;
	}
	resizePixels((unsigned int*)pixelsBuffer, videoSize[0], videoSize[1], SCALED_WIDTH, SCALED_HEIGHT);

	if (!startupFlag)
	{
		startupFlag = 1;
		// read registry and launch the player
		HKEY hKey;
		DWORD dwSize = MAX_PATH;
		DWORD dwType = REG_SZ;
		LPCTSTR studioPath = TEXT("studio");
		LPCTSTR playerPath = TEXT("player");
		if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, studioPath, 0, KEY_READ, &hKey) || 
			ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, playerPath, 0, KEY_READ, &hKey))
		{ 
			if (ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("install_location"), 0, &dwType, (LPBYTE)&mLocation, &dwSize))
			{
				installFlag = 1;
			}
			RegCloseKey(hKey);
		}
		else
		{
			ret = MessageBox(NULL, TEXT("We failed to find your Studio/Player installation。"), TEXT("Information"), MB_ICONINFORMATION | MB_OKCANCEL);
			
		} 
		if (installFlag)
		{
			HINSTANCE hInstance;
			hInstance = ShellExecute(NULL, TEXT("open"), mLocation, TEXT("previewplugin 2048 1024"), NULL, SW_SHOWNORMAL);
			LOGINFO(L"ShellExecute returns %d", (int)hInstance);
		}  
	}

	// get memory file mapping for pixels buffer.
	if (hPixelsMappingFile == NULL)
	{
		hPixelsMappingFile = CreateFileMapping(INVALID_HANDLE_VALUE,
			NULL,
			PAGE_READWRITE,
			0, RESIZED_BUFFER_SIZE,
			TEXT("pixels_buffer"));
		pbPixelsFile = (void*)MapViewOfFile(hPixelsMappingFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
	}

	if (hPixelsMappingFile != NULL && pbPixelsFile != NULL)
	{
		if (videoSize[0] / videoSize[1] == 2)
		{
			CopyMemory(pbPixelsFile, resizedBuffer, RESIZED_BUFFER_SIZE);
			FlushViewOfFile(pbPixelsFile, RESIZED_BUFFER_SIZE);
		}
	}

	...
	return tmResult_Success;
}

  通过查找注册表判断是否安装外部全景播放器。如果已安装则通过安装路径直接启动,否则提示用户。每一帧的数据通过内存共享暴露给外部全景播放器。播放器只需读取这块共享内存即可。至此编码工作完成,简单的不能再简单。将编译好的插件复制到Premiere的插件目录即可查看效果。

三、注意事项

  • 依赖库。如果插件依赖外部程序库,在安装的时候也要复制到插件安装目录,或者是windows系统目录,否则插件是无法正常加载的。要查看插件依赖哪些外部程序库,可以使用VS附带的dumpbin命令:dumpbin /imports。有的时候安装可能会混淆32位和64位程序,那么还阔以通过dumpbin /headers查看程序库的版本。
  • Premiere/After Effects使用的是ARGB颜色模型。因此在利用外部程序库处理时,可能需要进行适当的转换。
  • 权限问题。在高版本的windows上,VS调试系统盘的程序时需要以管理员权限运行打开工程,否则是无法启动程序调试的。

四、参考链接

1. https://forums.adobe.com/thread/1661575

2. http://www.kolor.com/kolor-eyes/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Premiere Pro & After Effects插件开发调试方法

          在给Adobe Premiere Pro(PR)和Adobe After Effects(AE)插件开发时,对于实时调试插件有着很强的需求。除了业务...

    24K纯开源
  • PR&AE插件开发遇到的一个坑

          经过一段时间的摸索,对Adobe Premiere Pro和After Effects系列插件的开发工作有了一定的掌握。如今公司需要针对Premie...

    24K纯开源
  • Adobe创新大会|Project Aero发布封闭内测版,Premiere Pro 13.0正式支持VR180格式

    美国时间10月15日,Adobe MAX 2018全球创新大会(以下统称为“Adobe创新大会”)已在洛杉矶拉开帷幕。

    VRPinea
  • 那些科技圈的弄潮儿不得不知道的VR剪辑软件!

    VRPinea
  • AE的Plugin开发流程

    效果插件可以应用于合成中的视频或音频,以处理视频和/或音频数据。内置效果的一些示例是亮度和容量,色调/饱和度,高斯模糊和变形稳定器。效果插件可以为用户提供一组参...

    jerrypxiao
  • Final Cut Pro X效果插件开发总结

    一、介绍       最近公司需要针对Final Cut Pro(FCP)开发一款效果插件,用于对公司自己开发的视频格式进行后期处理。Final Cut Pro...

    24K纯开源
  • KK 软件大师

    kk大数据
  • UI设计师必备的五款界面设计工具

    在前几篇文章中,我们分享了一些最受欢迎的原型设计工具,今天我们来谈谈界面设计工具。工具的重要性对于设计师来讲不言而喻。任何想法都需要借助工具来实现。想要成为一名...

    奔跑的小鹿
  • Windows平台LoadLibrary加载动态库搜索路径的问题

    在给Adobe Premiere/After Effects等后期制作软件开发第三方插件的时候,我们总希望插件依赖的动态库能够脱离插件的位置,单独存储到另外一个...

    24K纯开源
  • 相册的逆袭:Qzone5.5动画诞生记 - 腾讯ISUX

    腾讯ISUX
  • Mac 版 Adobe CC 2019 的日常更新。

    Adobe CC 2019 软件已经发布有一些时候了,由于2019更换了注册模块,所以新版软件的破解出来得很慢。Adobe Zii破解工具是由国外TNT大神制作...

    课代表
  • 如何制作《钢铁侠》中的炫酷界面(FUI)

    你是否想过许多科幻电影中,看到的所有炫酷的的显示画面如何制作的?如《钢铁侠》,《火星救援》,《奇异博士》,《银河护卫队》等等这些,其实都是在C4D的的制作与实现...

    宇相
  • amtlib.dll文件补丁

    amtlib.dll文件补丁,是Adobe CS6系列软件通用解除注册的补丁。amtlib.dll含32位与64位,使用本补丁后,就可以绕过注册直接使用软件了。

    爱游博客
  • 2020年最值得推荐的10款UI动效设计工具

    动效设计在最近几年的各种网页设计和App设计中的表现相当抢眼。各种令人惊叹的创意和流畅自然的动作设计迅速捕获了用户的视线,极大地提升了品质感和转化率。而要制作出...

    奔跑的小鹿
  • 带alpha透明通道视频—网页播放带alpha通道视频叠加合成方案

    带alpha通道的图片有GIF和PNG,但是GIF只有8位,失真严重,边缘锯齿非常明显。

    周陆军
  • 软件合集【WIN+MAC】 | 掌上编程

    后端码匠
  • [讨论]为设计工具付费到底值不值得?

    如今,越来越多的设计工具从免费转向了付费,越来越的设计师和公司也接受了付费的使用模式。不过,行业主流的设计工具往往来自欧美,定价通常都非常“不近国情”。拮据的国...

    用户5009027
  • PS 2021融入AI新技术!用起来简单,几个键搞定老照片修复、变妆、绘画风格转换

    PS 2021中,新增的功能“神经滤镜” (Neural Filters)令人惊艳,将近期有意思的CV(计算机视觉)技术都收入其中。

    AI算法与图像处理
  • 2019 VOD编码工具指南

    https://www.streamingmedia.com/Articles/Editorial/Featured-Articles/Buyers-Guide...

    LiveVideoStack

扫码关注云+社区

领取腾讯云代金券