Support DELPHI-FFMPEG in components

Signed-off-by: Laentir Valetov <laex@bk.ru>
This commit is contained in:
Laentir Valetov 2019-09-16 21:46:20 +04:00
parent 1c4b6a52fb
commit 4a57e35ca7
5 changed files with 304 additions and 29 deletions

View File

@ -15,7 +15,7 @@ or from the repository:
(1) 32-bit in the "Delphi-OpenCV\redist\VC14\x86\" (1) 32-bit in the "Delphi-OpenCV\redist\VC14\x86\"
(2) 64-bit in the "Delphi-OpenCV\redist\VC14\x64\" (2) 64-bit in the "Delphi-OpenCV\redist\VC14\x64\"
``` ```
* Shared library FFMPEG 4.0.2 for Windows can be downloaded from [here][5]<br> * Shared library FFMPEG 4.2 for Windows can be downloaded from [here][5]<br>
``` ```
(3) FFmpeg 32-bit Shared (3) FFmpeg 32-bit Shared
(4) FFmpeg 64-bit Shared (4) FFmpeg 64-bit Shared
@ -55,13 +55,13 @@ Unzip it to a convenient directory, thus get the following directory structure<b
<samples> <samples>
<source> <source>
``` ```
Download the [FFmpeg Delphi/Pascal Headers 4.0.2][6] and extract to <PROJECT_ROOT>\source\ffmpeg<br> Download the [FFmpeg Delphi/Pascal Headers 4.0.2][6] and extract to <PROJECT_ROOT>\source\ffmpeg or use [DELPHI-FFMPEG][7] (as submodule)<br>
Add the search path for the modules of the project in Delphi IDE (Tools-Options-Delphi Options-Library-Library path) Add the search path for the modules of the project in Delphi IDE (Tools-Options-Delphi Options-Library-Library path)
``` ```
<PROJECT_ROOT>\source <PROJECT_ROOT>\source
<PROJECT_ROOT>\source\classes <PROJECT_ROOT>\source\classes
<PROJECT_ROOT>\source\component <PROJECT_ROOT>\source\component
<PROJECT_ROOT>\source\ffmpeg\headers <PROJECT_ROOT>\source\ffmpeg\headers or <PROJECT_ROOT>\source\Delphi-FFMPEG\source
<PROJECT_ROOT>\source\opengl <PROJECT_ROOT>\source\opengl
<PROJECT_ROOT>\source\sdl <PROJECT_ROOT>\source\sdl
<PROJECT_ROOT>\source\sdl2 <PROJECT_ROOT>\source\sdl2
@ -131,3 +131,4 @@ Examples of use of components
[4]: https://github.com/opencv/opencv/releases/tag/2.4.13.3 [4]: https://github.com/opencv/opencv/releases/tag/2.4.13.3
[5]: http://ffmpeg.zeranoe.com/builds/ [5]: http://ffmpeg.zeranoe.com/builds/
[6]: http://www.delphiffmpeg.com/headers/ [6]: http://www.delphiffmpeg.com/headers/
[7]: https://github.com/Laex/Delphi-FFMPEG

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{9F27EBDE-3B7A-4B88-8E68-90DCA8A35F81}</ProjectGuid> <ProjectGuid>{9F27EBDE-3B7A-4B88-8E68-90DCA8A35F81}</ProjectGuid>
<ProjectVersion>18.6</ProjectVersion> <ProjectVersion>18.7</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>cCameraCapture.dpr</MainSource> <MainSource>cCameraCapture.dpr</MainSource>
<Base>True</Base> <Base>True</Base>

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{08BFF34B-6FF9-468C-9AB2-3F76BBC9E351}</ProjectGuid> <ProjectGuid>{08BFF34B-6FF9-468C-9AB2-3F76BBC9E351}</ProjectGuid>
<ProjectVersion>18.6</ProjectVersion> <ProjectVersion>18.7</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>cFFmpegIPCamSource.dpr</MainSource> <MainSource>cFFmpegIPCamSource.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
@ -214,6 +214,12 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_Colors">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon"> <DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir> <RemoteDir>res\drawable</RemoteDir>
@ -250,6 +256,36 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_NotificationIcon24">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426"> <DeployClass Name="Android_SplashImage426">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir> <RemoteDir>res\drawable-small</RemoteDir>
@ -274,6 +310,12 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_Strings">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols"> <DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator"> <Platform Name="iOSSimulator">
<Operation>1</Operation> <Operation>1</Operation>
@ -393,6 +435,17 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="iPad_Launch1024x768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536"> <DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
@ -404,6 +457,39 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="iPad_Launch1536x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668x2388">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048"> <DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
@ -415,6 +501,61 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="iPad_Launch2048x1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x2732">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2224">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2388x1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2732x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768"> <DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
@ -426,6 +567,116 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="iPad_Launch768x1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1136x640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242x2688">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1334">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1792">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2208">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2436">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2688x1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320"> <DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
@ -459,6 +710,28 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="iPhone_Launch750">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch828">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest"> <DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android"> <Platform Name="Android">
<Operation>1</Operation> <Operation>1</Operation>

@ -1 +1 @@
Subproject commit 0be92a08278ddc61978d326621038eebf4015ecb Subproject commit ed23a68bf58b5b2f19ad60673ed79a9389dd8b06

View File

@ -44,7 +44,7 @@ Uses
libavcodec; libavcodec;
Type Type
TOnNotifyFFMpegPacket = procedure(Sender: TObject; const packet: TAVPacket; const isKeyFrame: Boolean) of object; TOnNotifyFFMpegPacket = procedure(Sender: TObject; const packet: AVPacket; const isKeyFrame: Boolean) of object;
TocvFFMpegIPCamEvent = (ffocvTryConnect, ffocvConnected, ffocvLostConnection, ffocvReconnect, ffocvErrorGetStream); TocvFFMpegIPCamEvent = (ffocvTryConnect, ffocvConnected, ffocvLostConnection, ffocvReconnect, ffocvErrorGetStream);
TOnocvFFMpegIPCamEvent = procedure(Sender: TObject; const Event: TocvFFMpegIPCamEvent) of object; TOnocvFFMpegIPCamEvent = procedure(Sender: TObject; const Event: TocvFFMpegIPCamEvent) of object;
@ -66,7 +66,7 @@ Type
function GetIPCamTarget: AnsiString; function GetIPCamTarget: AnsiString;
procedure SetEnabled(Value: Boolean); override; procedure SetEnabled(Value: Boolean); override;
procedure Loaded; override; procedure Loaded; override;
procedure DoNotifyPacket(const packet: TAVPacket; const isKeyFrame: Boolean); procedure DoNotifyPacket(const packet: AVPacket; const isKeyFrame: Boolean);
procedure DoNotifyEvent(Event: TocvFFMpegIPCamEvent); procedure DoNotifyEvent(Event: TocvFFMpegIPCamEvent);
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
@ -89,11 +89,12 @@ Uses
ocv.core.types_c, ocv.core.types_c,
ocv.comp.Types, ocv.comp.Types,
libavformat, libavformat,
libavutil_dict, // libavutil_dict,
libavutil, libavutil,
libavutil_frame, // libavutil_frame,
libswscale, libswscale
libavutil_pixfmt; // ,libavutil_pixfmt
;
Type Type
TocvFFMpegIPCamSourceThread = class(TocvCustomSourceThread) TocvFFMpegIPCamSourceThread = class(TocvCustomSourceThread)
@ -139,7 +140,7 @@ begin
OnIPCamEvent(Self, Event); OnIPCamEvent(Self, Event);
end; end;
procedure TocvFFMpegIPCamSource.DoNotifyPacket(const packet: TAVPacket; const isKeyFrame: Boolean); procedure TocvFFMpegIPCamSource.DoNotifyPacket(const packet: AVPacket; const isKeyFrame: Boolean);
begin begin
if Assigned(OnFFMpegPacket) then if Assigned(OnFFMpegPacket) then
OnFFMpegPacket(Self, packet, isKeyFrame); OnFFMpegPacket(Self, packet, isKeyFrame);
@ -232,7 +233,7 @@ Var
pFormatCtx: pAVFormatContext; pFormatCtx: pAVFormatContext;
pCodecCtx: pAVCodecContext; pCodecCtx: pAVCodecContext;
pCodec: pAVCodec; pCodec: pAVCodec;
packet: TAVPacket; packet: AVPacket;
img_convert_context: pSwsContext; img_convert_context: pSwsContext;
frame: pAVFrame; frame: pAVFrame;
iplframe: pIplImage; iplframe: pIplImage;
@ -246,7 +247,7 @@ Var
end; end;
if Assigned(pFormatCtx) then if Assigned(pFormatCtx) then
begin begin
avformat_close_input(@pFormatCtx); avformat_close_input(pFormatCtx);
pFormatCtx := nil; pFormatCtx := nil;
end; end;
if Assigned(iplframe) then if Assigned(iplframe) then
@ -256,12 +257,12 @@ Var
end; end;
if Assigned(frame) then if Assigned(frame) then
begin begin
av_frame_free(@frame); av_frame_free(frame);
frame := nil; frame := nil;
end; end;
if Assigned(optionsDict) then if Assigned(optionsDict) then
begin begin
av_dict_free(@optionsDict); av_dict_free(optionsDict);
optionsDict := nil; optionsDict := nil;
end; end;
end; end;
@ -298,14 +299,14 @@ begin
DoNotyfy(ffocvTryConnect); DoNotyfy(ffocvTryConnect);
av_dict_set(@optionsDict, 'rtsp_transport', 'tcp', 0); av_dict_set(optionsDict, 'rtsp_transport', 'tcp', 0);
av_dict_set(@optionsDict, 'rtsp_flags', 'prefer_tcp', 0); av_dict_set(optionsDict, 'rtsp_flags', 'prefer_tcp', 0);
av_dict_set(@optionsDict, 'allowed_media_types', 'video', 0); av_dict_set(optionsDict, 'allowed_media_types', 'video', 0);
av_dict_set(@optionsDict, 'reorder_queue_size', '10', 0); av_dict_set(optionsDict, 'reorder_queue_size', '10', 0);
av_dict_set(@optionsDict, 'max_delay', '500000', 0); av_dict_set(optionsDict, 'max_delay', '500000', 0);
av_dict_set(@optionsDict, 'stimeout', '1000000', 0); av_dict_set(optionsDict, 'stimeout', '1000000', 0);
ret := avformat_open_input(@pFormatCtx, PAnsiChar(FIPCamURL), nil, @optionsDict); // pFormatCtx ret := avformat_open_input(pFormatCtx, PAnsiChar(FIPCamURL), nil, @optionsDict); // pFormatCtx
if ret < 0 then if ret < 0 then
begin begin
DoNotyfy(ffocvErrorGetStream); DoNotyfy(ffocvErrorGetStream);
@ -313,7 +314,7 @@ begin
Continue; Continue;
end; end;
av_dict_free(@optionsDict); av_dict_free(optionsDict);
optionsDict := nil; optionsDict := nil;
if avformat_find_stream_info(pFormatCtx, nil) < 0 then if avformat_find_stream_info(pFormatCtx, nil) < 0 then
begin begin
@ -368,8 +369,8 @@ begin
Continue; Continue;
end; end;
img_convert_context := sws_getCachedContext(nil, pCodecCtx^.Width, pCodecCtx^.Height, Integer(pCodecCtx^.pix_fmt), img_convert_context := sws_getCachedContext(nil, pCodecCtx^.Width, pCodecCtx^.Height, pCodecCtx^.pix_fmt,
pCodecCtx^.Width, pCodecCtx^.Height, Integer(AV_PIX_FMT_BGR24), SWS_BILINEAR, nil, nil, nil); pCodecCtx^.Width, pCodecCtx^.Height, AV_PIX_FMT_BGR24, SWS_BILINEAR, nil, nil, nil);
if (img_convert_context = nil) then if (img_convert_context = nil) then
begin begin
DoNotyfy(ffocvErrorGetStream); DoNotyfy(ffocvErrorGetStream);
@ -391,7 +392,7 @@ begin
begin begin
FOwner.DoNotifyPacket(packet, (packet.flags and AV_PKT_FLAG_KEY) <> 0); FOwner.DoNotifyPacket(packet, (packet.flags and AV_PKT_FLAG_KEY) <> 0);
// Video stream packet // Video stream packet
avcodec_decode_video2(pCodecCtx, frame, @frame_finished, @packet); avcodec_decode_video2(pCodecCtx, frame, frame_finished, @packet);
if (frame_finished <> 0) then if (frame_finished <> 0) then
begin begin
sws_scale(img_convert_context, @frame^.data, @frame^.linesize, 0, pCodecCtx^.Height, @iplframe^.imageData, sws_scale(img_convert_context, @frame^.data, @frame^.linesize, 0, pCodecCtx^.Height, @iplframe^.imageData,