mirror of
https://github.com/Laex/Delphi-OpenCV.git
synced 2024-11-18 01:05:53 +01:00
2f087607e5
Signed-off-by: Mikhail Grigorev <sleuthhound@gmail.com>
169 lines
4.5 KiB
ObjectPascal
169 lines
4.5 KiB
ObjectPascal
program scaling_video;
|
|
|
|
{$APPTYPE CONSOLE}
|
|
{$R *.res}
|
|
{$include ffmpeg.inc}
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Classes,
|
|
Winapi.Windows,
|
|
ffmpeglib,
|
|
ffmpeg.libavcodec.avcodec,
|
|
ffmpeg.ctypes,
|
|
ffmpeg.avformat,
|
|
ffmpeg.avio,
|
|
ffmpeg.avutil,
|
|
ffmpeg.buffer,
|
|
ffmpeg.dict,
|
|
ffmpeg.frame,
|
|
ffmpeg.log,
|
|
ffmpeg.opt,
|
|
ffmpeg.pixfmt,
|
|
ffmpeg.rational,
|
|
ffmpeg.samplefmt,
|
|
ffmpeg.parseutils,
|
|
ffmpeg.swscale,
|
|
ffmpeg.pixdesc,
|
|
ffmpeg.imgutils,
|
|
ffmpeg.mem,
|
|
ffmpeg.error,
|
|
uResourcePaths;
|
|
|
|
Var
|
|
src_data: TPointers;
|
|
dst_data: TPointers;
|
|
src_linesize: TLinesizes;
|
|
dst_linesize: TLinesizes;
|
|
src_w: Integer = 320;
|
|
src_h: Integer = 240;
|
|
dst_w, dst_h: Integer;
|
|
src_pix_fmt: TAVPixelFormat = AV_PIX_FMT_YUV420P;
|
|
dst_pix_fmt: TAVPixelFormat = AV_PIX_FMT_RGB24;
|
|
dst_size: AnsiString;
|
|
dst_filename: AnsiString;
|
|
// dst_file: File;
|
|
dst_straem:TMemoryStream;
|
|
dst_bufsize: Integer;
|
|
sws_ctx: pSwsContext = nil;
|
|
i, ret: Integer;
|
|
|
|
const
|
|
in_filename = cResourceMedia + 'trailer.avi';
|
|
out_filename = cResourceResult + 'trailer-out.avi';
|
|
|
|
procedure fill_yuv_image(data: TPointers; linesize: TLinesizes; width: Integer; height: Integer; frame_index: Integer);
|
|
Var
|
|
x, y: Integer;
|
|
begin
|
|
(* Y *)
|
|
for y := 0 to height - 1 do
|
|
for x := 0 to width - 1 do
|
|
data[0][y * linesize[0] + x] := x + y + frame_index * 3;
|
|
|
|
(* Cb and Cr *)
|
|
for y := 0 to height div 2 - 1 do
|
|
begin
|
|
for x := 0 to width div 2 - 1 do
|
|
begin
|
|
data[1][y * linesize[1] + x] := 128 + y + frame_index * 2;
|
|
data[2][y * linesize[2] + x] := 64 + x + frame_index * 5;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Var
|
|
Buf: array [0 .. 511] of AnsiChar;
|
|
r:Integer;
|
|
|
|
begin
|
|
try
|
|
if (ParamCount <> 2) then
|
|
begin
|
|
WriteLn(Format('Usage: %s output_file output_size' + #13#10 + 'API example program to show how to scale an image with libswscale.' +
|
|
#13#10 + 'This program generates a series of pictures, rescales them to the given ' +
|
|
'output_size and saves them to an output file named output_file.' + #13#10, [ExtractFileName(ParamStr(0))]));
|
|
end;
|
|
if (ParamCount < 2) then
|
|
begin
|
|
if FileExists(in_filename) then
|
|
if CopyFileEx(PChar(in_filename), PChar(out_filename), nil, nil, nil, COPY_FILE_RESTARTABLE) then
|
|
begin
|
|
dst_filename := out_filename;
|
|
dst_size := '320x240';
|
|
end
|
|
else
|
|
Halt(1);
|
|
end
|
|
else
|
|
begin
|
|
dst_filename := ParamStr(1);
|
|
dst_size := ParamStr(2);
|
|
end;
|
|
|
|
if av_parse_video_size(dst_w, dst_h, PAnsiChar(dst_size)) < 0 then
|
|
begin
|
|
WriteLn(Format('Invalid size %s, must be in the form WxH or a valid size abbreviation', [dst_size]));
|
|
Halt(1);
|
|
end;
|
|
|
|
(* create scaling context *)
|
|
sws_ctx := sws_getContext(src_w, src_h, src_pix_fmt, dst_w, dst_h, dst_pix_fmt, SWS_BILINEAR, Nil, Nil, Nil);
|
|
if not Assigned(sws_ctx) then
|
|
begin
|
|
WriteLn(Format('Impossible to create scale context for the conversion fmt:%s s:%dx%d -> fmt:%s s:%dx%d' + #13#10,
|
|
[av_get_pix_fmt_name(src_pix_fmt), src_w, src_h, av_get_pix_fmt_name(dst_pix_fmt), dst_w, dst_h]));
|
|
Halt(1);
|
|
// ret := AVERROR(EINVAL);
|
|
// goto
|
|
// end;
|
|
end;
|
|
|
|
(* allocate source and destination image buffers *)
|
|
ret := av_image_alloc(src_data, src_linesize, src_w, src_h, src_pix_fmt, 16);
|
|
// av_strerror(ret,@buf,SizeOf(buf));
|
|
if (ret < 0) then
|
|
begin
|
|
WriteLn('Could not allocate source image');
|
|
Halt(1);
|
|
end;
|
|
|
|
(* buffer is going to be written to rawvideo file, no alignment *)
|
|
ret := av_image_alloc(dst_data, dst_linesize, dst_w, dst_h, dst_pix_fmt, 1);
|
|
if (ret < 0) then
|
|
begin
|
|
WriteLn('Could not allocate destination image');
|
|
end;
|
|
dst_bufsize := ret;
|
|
|
|
dst_straem:=TMemoryStream.Create;
|
|
|
|
for i := 0 to 99 do
|
|
begin
|
|
(* generate synthetic video *)
|
|
fill_yuv_image(src_data, src_linesize, src_w, src_h, i);
|
|
|
|
(* convert to destination format *)
|
|
sws_scale(sws_ctx, @src_data, @src_linesize, 0, src_h, @dst_data, @dst_linesize);
|
|
|
|
(* write scaled image to file *)
|
|
dst_straem.Write((@dst_data[0][0])^, dst_bufsize);
|
|
end;
|
|
|
|
dst_straem.SaveToFile(dst_filename);
|
|
dst_straem.Free;
|
|
|
|
WriteLn(Format('Scaling succeeded. Play the output file with the command:' + #13#10 +
|
|
'ffplay -f rawvideo -pixel_format %s -video_size %dx%d %s', [av_get_pix_fmt_name(dst_pix_fmt), dst_w, dst_h, dst_filename]));
|
|
|
|
av_freep(@src_data[0]);
|
|
av_freep(@dst_data[0]);
|
|
sws_freeContext(sws_ctx);
|
|
|
|
except
|
|
on E: Exception do
|
|
WriteLn(E.ClassName, ': ', E.Message);
|
|
end;
|
|
|
|
end.
|