Delphi-OpenCV/samples/FFMpeg/scaling_video/scaling_video.dpr

169 lines
4.5 KiB
ObjectPascal
Raw Normal View History

program scaling_video;
{$APPTYPE CONSOLE}
{$R *.res}
{$i ffmpeg.inc}
uses
System.SysUtils,
System.Classes,
Winapi.Windows,
ffm.lib,
ffm.libavcodec.avcodec,
ffm.ctypes,
ffm.avformat,
ffm.avio,
ffm.avutil,
ffm.buffer,
ffm.dict,
ffm.frame,
ffm.log,
ffm.opt,
ffm.pixfmt,
ffm.rational,
ffm.samplefmt,
ffm.parseutils,
ffm.swscale,
ffm.pixdesc,
ffm.imgutils,
ffm.mem,
ffm.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.