wiki:

CompilationGuide

/

WinRT


Version 7 (modified by peter0302, 4 years ago) (diff)

The compilation guide did not address certain practical details and I have not found any other online source addressing it, so I thought this addition would be helpful. Ideally the FFmpeg team will incorporate full WinRT support into the next version. A separate page dedicated to FFmpeg usage in Windows Store apps may be warranted.

Compile and Use FFmpeg Libraries for Windows Runtime (WinRT)

FFmpeg libraries can be built for and used with Windows Store 8.1 and Windows Phone 8.1 apps development using MSVC 2013 (Update 3 RTM or newer). The guide below provides build instruction for all supported target configurations (platform & architecture). Each configuration requires distinct set of tools, environment variables, and configure options outlined in each section below. It concludes with some practical and potentially non-obvious information for consuming the FFmpeg DLLs from your app.


Prerequisites and First Time Setup Instructions

Prerequisites

MSYS2 Setup

Download the latest MSYS2 installer from http://msys2.github.io/ and follow the installation instruction

Once base MSYS2 is successfully installed, get the latest make package by invoking the following command in your MSYS2 shell

pacman -S make

Also get the latest gcc package

pacman -S gcc

Rename or remove link.exe in the MSYS2 usr bin folder (E.g. C:\msys64\usr\bin\link.exe) to prevent conflict with MSVC link.exe

Install perl as it will be needed to run 'gas-preprocessor.pl'

pacman -S perl

YASM Setup

Download YASM executable from http://yasm.tortall.net/Download.html. The last tested version was yasm-1.3.0-win64.exe.

Rename the downloaded executable to yasm.exe and place it in your MSYS2 path. E.g.C:\msys64\usr\bin\yasm.exe

gas-preprocessor Setup

Download gas-preprocessor.pl Perl script from https://github.com/FFmpeg/gas-preprocessor

Place the downloaded Perl script in your MSYS2 path. E.g. C:\msys64\usr\bin\gas-preprocessor.pl

Verifying your FFmpeg Environment Setup

Launch VS2013 ARM Cross Tools Command Prompt

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > VS2013 ARM Cross Tools Command Prompt

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In the MSYS2 shell verify that all the tools below are setup properly by running the following commands

$ which cl
/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/x86_ARM/cl

$ which link
/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/x86_ARM/link

$ which armasm
/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/x86_ARM/armasm

$ which yasm
/usr/bin/yasm

$ which cpp
/usr/bin/cpp

$ which gas-preprocessor.pl
/usr/bin/gas-preprocessor.pl

Verify that the tools are in the path and point to the right location where MSYS2 and Visual Studio are installed


To keep the source tree clean and the platforms separated, we will have the intermediate files go to the Output\<Platform>\<Architecture> folder under the FFmpeg source tree. We will also have the install files (the files necessary to link and use FFmpeg in your application) go to the Build\<Platform>\<Architecture> folder under the FFmpeg source tree.


Windows Store 8.1 x86 (Windows 8.1 Win32 in Visual Studio)

Launch Developer Command Prompt for VS2013

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > Developer Command Prompt for VS2013

Set the following environment variables in the launched command prompt above. These environment variables overwrite the default paths with correct target specific ones.

SET LIB=%VSINSTALLDIR%VC\lib\store;%VSINSTALLDIR%VC\atlmfc\lib;%WindowsSdkDir%lib\winv6.3\um\x86;;
SET LIBPATH=%WindowsSdkDir%References\CommonConfiguration\Neutral;;%VSINSTALLDIR%VC\atlmfc\lib;%VSINSTALLDIR%VC\lib;
SET INCLUDE=%VSINSTALLDIR%VC\include;%VSINSTALLDIR%VC\atlmfc\include;%WindowsSdkDir%Include\um;%WindowsSdkDir%Include\shared;%WindowsSdkDir%Include\winrt;;

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In your MSYS2 shell navigate to your cloned FFmpeg folder

Invoke the following make commands

mkdir -p Output/Windows81/Win32
cd Output/Windows81/Win32
../../../configure \
--toolchain=msvc \
--disable-programs \
--disable-dxva2 \
--arch=x86 \
--enable-shared \
--enable-cross-compile \
--target-os=win32 \
--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0603" \
--extra-ldflags="-winmd -appcontainer" \
--prefix=../../../Build/Windows81/Win32

make

make install

Generated libraries can be found in Build/Windows81/Win32 folder specified in --prefix option above


Windows Store 8.1 x64 (Windows 8.1 x64 in Visual Studio)

Launch VS2013 x64 Cross Tools Command Prompt

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > VS2013 x64 Cross Tools Command Prompt

Set the following environment variables in the launched command prompt above. These environment variables overwrite the default paths with correct target specific ones.

SET LIB=%VSINSTALLDIR%VC\lib\store\amd64;%VSINSTALLDIR%VC\atlmfc\lib\amd64;%WindowsSdkDir%lib\winv6.3\um\x64;;
SET LIBPATH=%WindowsSdkDir%References\CommonConfiguration\Neutral;;%VSINSTALLDIR%VC\atlmfc\lib\amd64;%VSINSTALLDIR%VC\lib\amd64;
SET INCLUDE=%VSINSTALLDIR%VC\include;%VSINSTALLDIR%VC\atlmfc\include;%WindowsSdkDir%Include\um;%WindowsSdkDir%Include\shared;%WindowsSdkDir%Include\winrt;;

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In your MSYS2 shell navigate to your cloned FFmpeg folder

Invoke the following make commands

mkdir -p Output/Windows81/x64
cd Output/Windows81/x64
../../../configure \
--toolchain=msvc \
--disable-programs \
--disable-dxva2 \
--arch=x86_64 \
--enable-shared \
--enable-cross-compile \
--target-os=win32 \
--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0603" \
--extra-ldflags="-winmd -appcontainer" \
--prefix=../../../Build/Windows81/x64

make

make install

Generated libraries can be found in Build/Windows81/x64 folder specified in --prefix option above


Windows Store 8.1 ARM (Windows 8.1 ARM in Visual Studio)

Launch VS2013 ARM Cross Tools Command Prompt

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > VS2013 ARM Cross Tools Command Prompt

Set the following environment variables in the launched command prompt above. These environment variables overwrite the default paths with correct target specific ones.

SET LIB=%VSINSTALLDIR%VC\lib\store\ARM;%VSINSTALLDIR%VC\atlmfc\lib\ARM;%WindowsSdkDir%lib\winv6.3\um\arm;;
SET LIBPATH=%WindowsSdkDir%References\CommonConfiguration\Neutral;;%VSINSTALLDIR%VC\atlmfc\lib\ARM;%VSINSTALLDIR%VC\lib\ARM;
SET INCLUDE=%VSINSTALLDIR%VC\include;%VSINSTALLDIR%VC\atlmfc\include;%WindowsSdkDir%Include\um;%WindowsSdkDir%Include\shared;%WindowsSdkDir%Include\winrt;;

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In your MSYS2 shell navigate to your cloned FFmpeg folder

Invoke the following make commands

mkdir -p Output/Windows81/ARM
cd Output/Windows81/ARM
../../../configure \
--toolchain=msvc \
--disable-programs \
--disable-dxva2 \
--arch=arm \
--as=armasm \
--cpu=armv7 \
--enable-thumb \
--enable-shared \
--enable-cross-compile \
--target-os=win32 \
--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0603 -D__ARM_PCS_VFP" \
--extra-ldflags="-MACHINE:ARM -winmd -appcontainer" \
--prefix=../../../Build/Windows81/ARM

make

make install

Generated libraries can be found in Build/Windows81/ARM folder specified in --prefix option above


Windows Phone 8.1 x86 (Windows Phone 8.1 Win32 Emulator in Visual Studio)

Launch Developer Command Prompt for VS2013

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > Developer Command Prompt for VS2013

Set the following environment variables in the launched command prompt above. These environment variables overwrite the default paths with correct target specific ones.

SET LIB=%VSINSTALLDIR%VC\lib\store;%VSINSTALLDIR%VC\atlmfc\lib;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\lib\x86;;
SET LIBPATH=%VSINSTALLDIR%VC\atlmfc\lib;%VSINSTALLDIR%VC\lib
SET INCLUDE=%VSINSTALLDIR%VC\INCLUDE;%VSINSTALLDIR%VC\ATLMFC\INCLUDE;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\abi;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\mincore;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\minwin;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\wrl;

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In your MSYS2 shell navigate to your cloned FFmpeg folder

Invoke the following make commands

mkdir -p Output/WindowsPhone81/Win32
cd Output/WindowsPhone81/Win32
../../../configure \
--toolchain=msvc \
--disable-programs \
--disable-dxva2 \
--arch=x86 \
--enable-shared \
--enable-cross-compile \
--target-os=win32 \
--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_WIN32_WINNT=0x0603" \
--extra-ldflags="-subsystem:console -opt:ref WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib -NODEFAULTLIB:kernel32.lib -NODEFAULTLIB:ole32.lib" \
--prefix=../../../Build/WindowsPhone81/Win32

make

make install

Generated libraries can be found in Build/WindowsPhone81/Win32 folder specified in --prefix option above


Windows Phone 8.1 ARM (Windows Phone 8.1 ARM Device in Visual Studio)

Launch VS2013 ARM Cross Tools Command Prompt

Start Menu > Visual Studio 2013 (Start Menu Folder) > Visual Studio Tools > VS2013 ARM Cross Tools Command Prompt

Set the following environment variables in the launched command prompt above. These environment variables overwrite the default paths with correct target specific ones.

SET LIB=%VSINSTALLDIR%VC\lib\store\ARM;%VSINSTALLDIR%VC\atlmfc\lib\ARM;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\lib\arm;;
SET LIBPATH=%VSINSTALLDIR%VC\atlmfc\lib\ARM;%VSINSTALLDIR%VC\lib\ARM
SET INCLUDE=%VSINSTALLDIR%VC\include;%VSINSTALLDIR%VC\atlmfc\include;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\abi;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\mincore;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\minwin;%WindowsSdkDir%..\..\Windows Phone Kits\8.1\Include\wrl;

Open MSYS2 shell from the command prompt above (use the correct drive and location of your MSYS2 installation). Note that the command shell above will close and it may take a while for the MSYS2 shell to launch.

C:\msys64\msys2_shell.bat

In your MSYS2 shell navigate to your cloned FFmpeg folder

Invoke the following make commands

mkdir -p Output/WindowsPhone81/ARM
cd Output/WindowsPhone81/ARM
../../../configure \
--toolchain=msvc \
--disable-programs \
--disable-dxva2 \
--arch=arm \
--as=armasm \
--cpu=armv7 \
--enable-thumb \
--enable-shared \
--enable-cross-compile \
--target-os=win32 \
--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_WIN32_WINNT=0x0603 -D__ARM_PCS_VFP" \
--extra-ldflags="-MACHINE:ARM -subsystem:console -opt:ref WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib -NODEFAULTLIB:kernel32.lib -NODEFAULTLIB:ole32.lib" \
--prefix=../../../Build/WindowsPhone81/ARM

make

make install

Generated libraries can be found in Build/WindowsPhone81/ARM folder specified in --prefix option above


Windows Store Certification, File I/O, and Other Details

FFmpeg is an excellent alternative to Windows Media Foundation, which supports a small fraction of the codecs that FFmpeg has. Fortunately, FFmpeg does not use any prohibited Windows or CRT APIs, and apps linked to the DLLs built with this method pass the latest Windows App Certification Kit. However, there are important things to remember.

First, don't forget to make sure your app package includes all the necessary FFmpeg DLLs in the root folder. In your Visual C++ project, you should include links to the FFmpeg DLLs in the root project folder, making sure to set "Build Action" to "Content" and "Copy to Output Directory" to "Copy Always". It is not enough just to link to the import libraries. You will fail certification if you require your users to install the FFmpeg DLLs separately.

You will also need to supply a custom file I/O context to any AVFormatContext rather than relying on avio_xxx functions, because the standard I/O functions utilize CRT I/O that is not supported in WinRT. (You won't fail certification, but your app will be unable to access the file specified in the AVFormatContext.filename member, unless potentially it is located in the app's local storage). The file I/O context needs to be initialized to point to your read, write, and seek functions, with the opaque member pointing to a struct containing an IRandomAccessStream^ that you obtain when opening a file using proper WinRT IO calls in the Windows::Storage namespace. (You need a struct to hold the IRandomAccessStream^, since you cannot cast a void* to a ref handle). Your read, write, and seek functions should cast the void* opaque argument to the struct* you define, and then use the IRandomAccessStream^ for all I/O.

Since FFmpeg I/O calls are synchronous, but the IRandomAccessStream members are all asynchronous, you will need to utilize create_task and wait() on all I/O calls in your IO context implementation functions. Note that this necessitates that any FFmpeg functions utilizing file I/O be executed on a WORKER thread, as WinRT will generate an exception if you use wait() in the UI thread. The best solution here is to create WinRT-friendly wrapper functions of the major FFmpeg functions you will utilize, by using the concurrency::create_async function, for example:

IAsyncOperation<int>^ av_read_frame_async(AVFormatContext* s, AVPacket* pkt)
{
	return create_async([s, pkt]()->int
	{
		return av_read_frame(s, pkt);
	});
}

Alternatively, if you don't want to use Windows Runtime extensions, and don't mind COM, you can use the Windows 8-API function CreateStreamOverRandomAccessStream, which gives you an IStream* COM interface from an IRandomAccessStream^, utilizes synchronous I/O, and can be passed as the void* opaque member of the IO context. The IStream I/O calls are easier to use with C++ since they support direct pointer buffer access (you don't have to deal with IBuffer) and more closely correspond to the functions required in AVIOContext. However, you should still make sure to wrap any code that utilizes file I/O in a background thread, as excessive blocking of the UI does violate Windows Store guidelines and may cause your app to be terminated at runtime.