mirror of
https://github.com/Laex/Delphi-OpenCV.git
synced 2024-11-15 15:55:53 +01:00
Fixed issues.
Signed-off-by: Laentir Valetov <laex@bk.ru>
This commit is contained in:
parent
19c2916c0d
commit
a0a8c8d419
693
samples/FFMpeg/decoding_encoding/decoding_encoding.dpr
Normal file
693
samples/FFMpeg/decoding_encoding/decoding_encoding.dpr
Normal file
@ -0,0 +1,693 @@
|
||||
(*
|
||||
* Copyright (c) 2001 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*)
|
||||
(* *
|
||||
* @file
|
||||
* libavcodec API use example.
|
||||
*
|
||||
* @example decoding_encoding.c
|
||||
* Note that libavcodec only handles codecs (mpeg, mpeg4, etc...),
|
||||
* not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the
|
||||
* format handling
|
||||
*)
|
||||
|
||||
program decoding_encoding;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
{$POINTERMATH ON}
|
||||
{$R *.res}
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Math,
|
||||
ffm.libavcodec.avcodec,
|
||||
ffm.pixfmt,
|
||||
ffm.avformat,
|
||||
ffm.samplefmt,
|
||||
ffm.swscale,
|
||||
ffm.avio,
|
||||
ffm.frame,
|
||||
ffm.channel_layout,
|
||||
ffm.ctypes,
|
||||
ffm.mem,
|
||||
ffm.mathematics,
|
||||
ffm.avutil,
|
||||
ffm.opt,
|
||||
ffm.imgutils;
|
||||
|
||||
Const
|
||||
INBUF_SIZE = 4096;
|
||||
AUDIO_INBUF_SIZE = 20480;
|
||||
AUDIO_REFILL_THRESH = 4096;
|
||||
|
||||
(* check that a given sample format is supported by the encoder *)
|
||||
function check_sample_fmt(const codec: pAVCodec; const sample_fmt: TAVSampleFormat): Boolean;
|
||||
Var
|
||||
p: pAVSampleFormat;
|
||||
begin
|
||||
p := codec^.sample_fmts;
|
||||
while (p^ <> AV_SAMPLE_FMT_NONE) do
|
||||
begin
|
||||
if (p^ = sample_fmt) then
|
||||
Exit(True);
|
||||
inc(p);
|
||||
end;
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
(* just pick the highest supported samplerate *)
|
||||
function select_sample_rate(const codec: pAVCodec): Integer;
|
||||
Var
|
||||
p: pInteger;
|
||||
best_samplerate: Integer;
|
||||
begin
|
||||
best_samplerate := 0;
|
||||
if not Assigned(codec^.supported_samplerates) then
|
||||
Exit(44100);
|
||||
p := codec^.supported_samplerates;
|
||||
while (p^ <> 0) do
|
||||
begin
|
||||
best_samplerate := MAX(p^, best_samplerate);
|
||||
inc(p);
|
||||
end;
|
||||
Result := best_samplerate;
|
||||
end;
|
||||
|
||||
(* select layout with the highest channel count *)
|
||||
function select_channel_layout(codec: pAVCodec): Integer;
|
||||
Var
|
||||
p: PUInt64_t;
|
||||
best_ch_layout: UInt64;
|
||||
best_nb_channels: Integer;
|
||||
nb_channels: Integer;
|
||||
begin
|
||||
best_ch_layout := 0;
|
||||
best_nb_channels := 0;
|
||||
if not Assigned(codec^.channel_layouts) then
|
||||
Exit(AV_CH_LAYOUT_STEREO);
|
||||
p := codec^.channel_layouts;
|
||||
while (p^ <> 0) do
|
||||
begin
|
||||
nb_channels := av_get_channel_layout_nb_channels(p^);
|
||||
if (nb_channels > best_nb_channels) then
|
||||
begin
|
||||
best_ch_layout := p^;
|
||||
best_nb_channels := nb_channels;
|
||||
end;
|
||||
inc(p);
|
||||
end;
|
||||
Result := best_ch_layout;
|
||||
end;
|
||||
|
||||
(*
|
||||
* Audio encoding example
|
||||
*)
|
||||
procedure audio_encode_example(const filename: String);
|
||||
Var
|
||||
codec: pAVCodec;
|
||||
c: pAVCodecContext;
|
||||
frame: pAVFrame;
|
||||
pkt: TAVPacket;
|
||||
i, j, k, ret, got_output: Integer;
|
||||
buffer_size: Integer;
|
||||
f: File;
|
||||
samples: ^Int16;
|
||||
t, tincr: Single;
|
||||
begin
|
||||
c := nil;
|
||||
WriteLn('Encode audio file ', filename);
|
||||
(* find the MP2 encoder *)
|
||||
codec := avcodec_find_encoder(AV_CODEC_ID_MP2);
|
||||
if not Assigned(codec) then
|
||||
begin
|
||||
WriteLn('Codec not found');
|
||||
Exit;
|
||||
end;
|
||||
c := avcodec_alloc_context3(codec);
|
||||
if not Assigned(c) then
|
||||
begin
|
||||
WriteLn('Could not allocate audio codec context\n');
|
||||
Exit;
|
||||
end;
|
||||
(* put sample parameters *)
|
||||
c^.bit_rate := 64000;
|
||||
(* check that the encoder supports s16 pcm input *)
|
||||
c^.sample_fmt := AV_SAMPLE_FMT_S16;
|
||||
if not check_sample_fmt(codec, c^.sample_fmt) then
|
||||
begin
|
||||
WriteLn('Encoder does not support sample format ', av_get_sample_fmt_name(c^.sample_fmt));
|
||||
Exit;
|
||||
end;
|
||||
(* select other audio parameters supported by the encoder *)
|
||||
c^.sample_rate := select_sample_rate(codec);
|
||||
c^.channel_layout := select_channel_layout(codec);
|
||||
c^.channels := av_get_channel_layout_nb_channels(c^.channel_layout);
|
||||
(* open it *)
|
||||
if (avcodec_open2(c, codec, nil) < 0) then
|
||||
begin
|
||||
WriteLn('Could not open codec');
|
||||
Exit;
|
||||
end;
|
||||
AssignFile(f, filename);
|
||||
try
|
||||
Rewrite(f, 1);
|
||||
except
|
||||
WriteLn('Could not open', filename);
|
||||
Exit;
|
||||
end;
|
||||
(* frame containing input raw audio *)
|
||||
frame := av_frame_alloc();
|
||||
if not Assigned(frame) then
|
||||
begin
|
||||
WriteLn('Could not allocate audio frame');
|
||||
Exit;
|
||||
end;
|
||||
frame^.nb_samples := c^.frame_size;
|
||||
frame^.format := Integer(c^.sample_fmt);
|
||||
frame^.channel_layout := c^.channel_layout;
|
||||
(* the codec gives us the frame size, in samples,
|
||||
* we calculate the size of the samples buffer in bytes *)
|
||||
buffer_size := av_samples_get_buffer_size(nil, c^.channels, c^.frame_size, c^.sample_fmt, 0);
|
||||
if (buffer_size < 0) then
|
||||
begin
|
||||
WriteLn('Could not get sample buffer size');
|
||||
Exit;
|
||||
end;
|
||||
samples := av_malloc(buffer_size);
|
||||
if not Assigned(samples) then
|
||||
begin
|
||||
WriteLn('Could not allocate %d bytes for samples buffer\n', buffer_size);
|
||||
Exit;
|
||||
end;
|
||||
(* setup the data pointers in the AVFrame *)
|
||||
ret := avcodec_fill_audio_frame(frame, c^.channels, c^.sample_fmt, pByte(samples), buffer_size, 0);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Could not setup audio frame');
|
||||
Exit;
|
||||
end;
|
||||
(* encode a single tone sound *)
|
||||
t := 0;
|
||||
tincr := 2 * M_PI * 440.0 / c^.sample_rate;
|
||||
for i := 0 to 199 do
|
||||
begin
|
||||
av_init_packet(@pkt);
|
||||
pkt.data := nil; // packet data will be allocated by the encoder
|
||||
pkt.size := 0;
|
||||
for j := 0 to c^.frame_size - 1 do
|
||||
begin
|
||||
samples[2 * j] := Trunc((sin(t) * 10000));
|
||||
for k := 1 to c^.channels - 1 do
|
||||
samples[2 * j + k] := samples[2 * j];
|
||||
t := t + tincr;
|
||||
end;
|
||||
(* encode the samples *)
|
||||
ret := avcodec_encode_audio2(c, @pkt, frame, got_output);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Error encoding audio frame');
|
||||
Exit;
|
||||
end;
|
||||
if (got_output <> 0) then
|
||||
begin
|
||||
BlockWrite(f, pkt.data^, pkt.size);
|
||||
av_free_packet(pkt);
|
||||
end;
|
||||
end;
|
||||
(* get the delayed frames *)
|
||||
got_output := 1;
|
||||
while got_output <> 0 do
|
||||
// ; i++)
|
||||
begin
|
||||
ret := avcodec_encode_audio2(c, @pkt, nil, got_output);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Error encoding frame');
|
||||
Exit;
|
||||
end;
|
||||
if (got_output <> 0) then
|
||||
begin
|
||||
BlockWrite(f, pkt.data^, pkt.size);
|
||||
av_free_packet(pkt);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
Close(f);
|
||||
av_freep(samples);
|
||||
av_frame_free(frame);
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
end;
|
||||
|
||||
(*
|
||||
* Audio decoding.
|
||||
*)
|
||||
procedure audio_decode_example(const outfilename: String; const filename: String);
|
||||
Var
|
||||
codec: pAVCodec;
|
||||
c: pAVCodecContext;
|
||||
len: Integer;
|
||||
f, outfile: File;
|
||||
inbuf: array [0 .. AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE - 1] of byte;
|
||||
avpkt: TAVPacket;
|
||||
decoded_frame: pAVFrame;
|
||||
got_frame: Integer;
|
||||
data_size: Integer;
|
||||
begin
|
||||
c := nil;
|
||||
decoded_frame := nil;
|
||||
av_init_packet(@avpkt);
|
||||
WriteLn('Decode audio file %s to ', filename, outfilename);
|
||||
(* find the mpeg audio decoder *)
|
||||
codec := avcodec_find_decoder(AV_CODEC_ID_MP2);
|
||||
if not Assigned(codec) then
|
||||
begin
|
||||
WriteLn('Codec not found');
|
||||
Exit;
|
||||
end;
|
||||
c := avcodec_alloc_context3(codec);
|
||||
if not Assigned(c) then
|
||||
begin
|
||||
WriteLn('Could not allocate audio codec context');
|
||||
Exit;
|
||||
end;
|
||||
(* open it *)
|
||||
if (avcodec_open2(c, codec, nil) < 0) then
|
||||
begin
|
||||
WriteLn('Could not open codec');
|
||||
Exit;
|
||||
end;
|
||||
AssignFile(f, filename);
|
||||
try
|
||||
Reset(f, 1);
|
||||
except
|
||||
WriteLn('Could not open ', filename);
|
||||
Exit;
|
||||
end;
|
||||
AssignFile(outfile, outfilename);
|
||||
try
|
||||
Rewrite(outfile, 1);
|
||||
except
|
||||
av_free(c);
|
||||
Exit;
|
||||
end;
|
||||
(* decode until eof *)
|
||||
avpkt.data := @inbuf;
|
||||
BlockRead(f, inbuf, AUDIO_INBUF_SIZE, avpkt.size);
|
||||
while (avpkt.size > 0) do
|
||||
begin
|
||||
got_frame := 0;
|
||||
if not Assigned(decoded_frame) then
|
||||
begin
|
||||
decoded_frame := av_frame_alloc();
|
||||
if not Assigned(decoded_frame) then
|
||||
begin
|
||||
WriteLn('Could not allocate audio frame');
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
len := avcodec_decode_audio4(c, decoded_frame, got_frame, @avpkt);
|
||||
if (len < 0) then
|
||||
begin
|
||||
WriteLn('Error while decoding');
|
||||
Exit;
|
||||
end;
|
||||
if (got_frame <> 0) then
|
||||
begin
|
||||
(* if a frame has been decoded, output it *)
|
||||
data_size := av_samples_get_buffer_size(nil, c^.channels, decoded_frame^.nb_samples, c^.sample_fmt, 1);
|
||||
if (data_size < 0) then
|
||||
begin
|
||||
(* This should not occur, checking just for paranoia *)
|
||||
WriteLn('Failed to calculate data size');
|
||||
Exit;
|
||||
end;
|
||||
BlockWrite(outfile, decoded_frame^.data[0]^, data_size);
|
||||
end;
|
||||
avpkt.size := avpkt.size - len;
|
||||
avpkt.data := avpkt.data + len;
|
||||
avpkt.dts := AV_NOPTS_VALUE;
|
||||
avpkt.pts := AV_NOPTS_VALUE;
|
||||
if (avpkt.size < AUDIO_REFILL_THRESH) then
|
||||
begin
|
||||
(* Refill the input buffer, to avoid trying to decode
|
||||
* incomplete frames. Instead of this, one could also use
|
||||
* a parser, or use a proper container format through
|
||||
* libavformat. *)
|
||||
Move(avpkt.data^, inbuf, avpkt.size);
|
||||
avpkt.data := @inbuf;
|
||||
BlockRead(f, avpkt.data[avpkt.size], AUDIO_INBUF_SIZE - avpkt.size, len);
|
||||
if (len > 0) then
|
||||
avpkt.size := avpkt.size + len;
|
||||
end;
|
||||
end;
|
||||
Close(outfile);
|
||||
Close(f);
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
av_frame_free(decoded_frame);
|
||||
end;
|
||||
|
||||
(*
|
||||
* Video encoding example
|
||||
*)
|
||||
procedure video_encode_example(const filename: String; codec_id: TAVCodecID);
|
||||
Var
|
||||
codec: pAVCodec;
|
||||
c: pAVCodecContext;
|
||||
i, ret, x, y, got_output: Integer;
|
||||
f: File;
|
||||
frame: pAVFrame;
|
||||
pkt: TAVPacket;
|
||||
endcode: array [0 .. 3] of byte;
|
||||
begin
|
||||
c := nil;
|
||||
endcode[0] := 0;
|
||||
endcode[1] := 0;
|
||||
endcode[2] := 1;
|
||||
endcode[3] := $B7;
|
||||
WriteLn('Encode video file ', filename);
|
||||
(* find the mpeg1 video encoder *)
|
||||
codec := avcodec_find_encoder(codec_id);
|
||||
if not Assigned(codec) then
|
||||
begin
|
||||
WriteLn('Codec not found');
|
||||
Exit;
|
||||
end;
|
||||
c := avcodec_alloc_context3(codec);
|
||||
if not Assigned(c) then
|
||||
begin
|
||||
WriteLn('Could not allocate video codec context');
|
||||
Exit;
|
||||
end;
|
||||
(* put sample parameters *)
|
||||
c^.bit_rate := 400000;
|
||||
(* resolution must be a multiple of two *)
|
||||
c^.width := 352;
|
||||
c^.height := 288;
|
||||
(* frames per second *)
|
||||
c^.time_base.num := 1;
|
||||
c^.time_base.den := 25;
|
||||
(* emit one intra frame every ten frames
|
||||
* check frame pict_type before passing frame
|
||||
* to encoder, if frame^.pict_type is AV_PICTURE_TYPE_I
|
||||
* then gop_size is ignored and the output of encoder
|
||||
* will always be I frame irrespective to gop_size
|
||||
*)
|
||||
c^.gop_size := 10;
|
||||
c^.max_b_frames := 1;
|
||||
c^.pix_fmt := AV_PIX_FMT_YUV420P;
|
||||
if (codec_id = AV_CODEC_ID_H264) then
|
||||
av_opt_set(c^.priv_data, 'preset', 'slow', 0);
|
||||
(* open it *)
|
||||
if (avcodec_open2(c, codec, nil) < 0) then
|
||||
begin
|
||||
WriteLn('Could not open codec');
|
||||
Exit;
|
||||
end;
|
||||
AssignFile(f, filename);
|
||||
try
|
||||
Rewrite(f, 1);
|
||||
except
|
||||
WriteLn('Could not open ', filename);
|
||||
Exit;
|
||||
end;
|
||||
frame := av_frame_alloc();
|
||||
if not Assigned(frame) then
|
||||
begin
|
||||
WriteLn('Could not allocate video frame');
|
||||
Exit;
|
||||
end;
|
||||
frame^.format := Integer(c^.pix_fmt);
|
||||
frame^.width := c^.width;
|
||||
frame^.height := c^.height;
|
||||
(* the image can be allocated by any means and av_image_alloc() is
|
||||
* just the most convenient way if av_malloc() is to be used *)
|
||||
ret := av_image_alloc(frame^.data, frame^.linesize, c^.width, c^.height, c^.pix_fmt, 32);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Could not allocate raw picture buffer');
|
||||
Exit;
|
||||
end;
|
||||
// got_output:=0;
|
||||
(* encode 1 second of video *)
|
||||
for i := 0 to 24 do
|
||||
begin
|
||||
av_init_packet(@pkt);
|
||||
pkt.data := nil; // packet data will be allocated by the encoder
|
||||
pkt.size := 0;
|
||||
(* prepare a dummy image *)
|
||||
|
||||
(* Y *)
|
||||
for y := 0 to c^.height - 1 do
|
||||
for x := 0 to c^.width - 1 do
|
||||
frame^.data[0][y * frame^.linesize[0] + x] := x + y + i * 3;
|
||||
|
||||
(* Cb and Cr *)
|
||||
for y := 0 to (c^.height div 2) - 1 do
|
||||
for x := 0 to (c^.width div 2) - 1 do
|
||||
begin
|
||||
frame^.data[1][y * frame^.linesize[1] + x] := 128 + y + i * 2;
|
||||
frame^.data[2][y * frame^.linesize[2] + x] := 64 + x + i * 5;
|
||||
end;
|
||||
|
||||
frame^.pts := i;
|
||||
(* encode the image *)
|
||||
ret := avcodec_encode_video2(c, @pkt, frame, got_output);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Error encoding frame');
|
||||
Exit;
|
||||
end;
|
||||
if (got_output <> 0) then
|
||||
begin
|
||||
WriteLn(format('Write frame %3d (size=%5d)', [i, pkt.size]));
|
||||
BlockWrite(f, pkt.data^, pkt.size);
|
||||
av_free_packet(pkt);
|
||||
end;
|
||||
end;
|
||||
(* get the delayed frames *)
|
||||
got_output := 1;
|
||||
While got_output <> 0 do
|
||||
begin
|
||||
ret := avcodec_encode_video2(c, @pkt, nil, got_output);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
WriteLn('Error encoding frame');
|
||||
Exit;
|
||||
end;
|
||||
if (got_output <> 0) then
|
||||
begin
|
||||
WriteLn(format('Write frame %3d (size=%5d)', [i, pkt.size]));
|
||||
BlockWrite(f, pkt.data^, pkt.size);
|
||||
av_free_packet(pkt);
|
||||
end;
|
||||
Inc(i);
|
||||
end;
|
||||
(* add sequence end code to have a real mpeg file *)
|
||||
BlockWrite(f, endcode, sizeof(endcode));
|
||||
Close(f);
|
||||
// avcodec_close(c);
|
||||
av_free(c);
|
||||
// av_freep(frame^.data[0]);
|
||||
av_frame_free(frame);
|
||||
end;
|
||||
|
||||
(*
|
||||
* Video decoding example
|
||||
*)
|
||||
procedure pgm_save(buf: pByte; wrap, xsize, ysize: Integer; filename: String);
|
||||
Var
|
||||
f: TextFile;
|
||||
fb: File;
|
||||
i: Integer;
|
||||
begin
|
||||
AssignFile(f, filename);
|
||||
Rewrite(f);
|
||||
WriteLn(f, format('P5' + #13#10 + '%d %d' + #13#10 + '%d', [xsize, ysize, 255]));
|
||||
Close(f);
|
||||
AssignFile(fb, filename);
|
||||
Reset(fb, 1);
|
||||
Seek(fb, FileSize(fb));
|
||||
for i := 0 to ysize - 1 do
|
||||
BlockWrite(fb, buf[i * wrap], xsize);
|
||||
Close(fb);
|
||||
end;
|
||||
|
||||
function decode_write_frame(const outfilename: String; avctx: pAVCodecContext; frame: pAVFrame;
|
||||
Var frame_count: Integer; pkt: pAVPacket; last: Integer): Integer;
|
||||
Var
|
||||
len, got_frame: Integer;
|
||||
buf: array [0 .. 1023] of AnsiChar;
|
||||
|
||||
begin
|
||||
len := avcodec_decode_video2(avctx, frame, got_frame, pkt);
|
||||
if (len < 0) then
|
||||
begin
|
||||
WriteLn('Error while decoding frame ', frame_count);
|
||||
Exit(len);
|
||||
end;
|
||||
if (got_frame <> 0) then
|
||||
begin
|
||||
if last <> 0 then
|
||||
WriteLn(format('Saving last frame %3d', [frame_count]))
|
||||
else
|
||||
WriteLn(format('Saving frame %3d', [frame_count]));
|
||||
(* the picture is allocated by the decoder, no need to free it *)
|
||||
pgm_save(frame^.data[0], frame^.linesize[0], avctx^.width, avctx^.height, Format(outfilename, [frame_count]));
|
||||
inc(frame_count);
|
||||
end;
|
||||
if Assigned(pkt^.data) then
|
||||
begin
|
||||
pkt^.size := pkt^.size - len;
|
||||
pkt^.data := pkt^.data + len;
|
||||
end;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure video_decode_example(const outfilename: String; const filename: String);
|
||||
Var
|
||||
codec: pAVCodec;
|
||||
c: pAVCodecContext;
|
||||
frame_count: Integer;
|
||||
f: File;
|
||||
frame: pAVFrame;
|
||||
inbuf: array [0 .. INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE - 1] of byte;
|
||||
avpkt: TAVPacket;
|
||||
begin
|
||||
c := nil;
|
||||
av_init_packet(@avpkt);
|
||||
(* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) *)
|
||||
FillChar(inbuf[INBUF_SIZE], FF_INPUT_BUFFER_PADDING_SIZE, 0);
|
||||
WriteLn(format('Decode video file %s to %s', [filename, outfilename]));
|
||||
(* find the mpeg1 video decoder *)
|
||||
codec := avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
|
||||
if not Assigned(codec) then
|
||||
begin
|
||||
WriteLn('Codec not found');
|
||||
Exit;
|
||||
end;
|
||||
c := avcodec_alloc_context3(codec);
|
||||
if not Assigned(c) then
|
||||
begin
|
||||
WriteLn('Could not allocate video codec context');
|
||||
Exit;
|
||||
end;
|
||||
if (codec^.capabilities and CODEC_CAP_TRUNCATED) <> 0 then
|
||||
c^.flags := c^.flags or CODEC_FLAG_TRUNCATED; (* we do not send complete frames *)
|
||||
(* For some codecs, such as msmpeg4 and mpeg4, width and height
|
||||
MUST be initialized there because this information is not
|
||||
available in the bitstream. *)
|
||||
(* open it *)
|
||||
if (avcodec_open2(c, codec, nil) < 0) then
|
||||
begin
|
||||
WriteLn('Could not open codec');
|
||||
Exit;
|
||||
end;
|
||||
AssignFile(f, filename);
|
||||
try
|
||||
Reset(f, 1);
|
||||
except
|
||||
WriteLn('Could not open ', filename);
|
||||
Exit;
|
||||
end;
|
||||
frame := av_frame_alloc();
|
||||
if not Assigned(frame) then
|
||||
begin
|
||||
WriteLn('Could not allocate video frame');
|
||||
Exit;
|
||||
end;
|
||||
frame_count := 0;
|
||||
While True do
|
||||
begin
|
||||
BlockRead(f, inbuf, INBUF_SIZE, avpkt.size);
|
||||
if (avpkt.size = 0) then
|
||||
break;
|
||||
(* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
|
||||
and this is the only method to use them because you cannot
|
||||
know the compressed data size before analysing it.
|
||||
BUT some other codecs (msmpeg4, mpeg4) are inherently frame
|
||||
based, so you must call them with all the data for one
|
||||
frame exactly. You must also initialize 'width' and
|
||||
'height' before initializing them. *)
|
||||
(* NOTE2: some codecs allow the raw parameters (frame size,
|
||||
sample rate) to be changed at any frame. We handle this, so
|
||||
you should also take care of it *)
|
||||
(* here, we use a stream based decoder (mpeg1video), so we
|
||||
feed decoder and see if it could decode a frame *)
|
||||
avpkt.data := @inbuf;
|
||||
while (avpkt.size > 0) do
|
||||
if (decode_write_frame(outfilename, c, frame, frame_count, @avpkt, 0) < 0) then
|
||||
Exit;
|
||||
end;
|
||||
(* some codecs, such as MPEG, transmit the I and P frame with a
|
||||
latency of one frame. You must do the following to have a
|
||||
chance to get the last frame of the video *)
|
||||
avpkt.data := nil;
|
||||
avpkt.size := 0;
|
||||
decode_write_frame(outfilename, c, frame, frame_count, @avpkt, 1);
|
||||
Close(f);
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
av_frame_free(frame);
|
||||
end;
|
||||
|
||||
Var
|
||||
output_type: String;
|
||||
|
||||
begin
|
||||
try
|
||||
(* register all the codecs *)
|
||||
avcodec_register_all();
|
||||
if ParamCount = 0 then
|
||||
begin
|
||||
WriteLn('usage: ' + ExtractFileName(ParamStr(0)) + ' output_type' + #13#10 +
|
||||
'API example program to decode/encode a media stream with libavcodec.' + #13#10 +
|
||||
'This program generates a synthetic stream and encodes it to a file' + #13#10 +
|
||||
'named test.h264, test.mp2 or test.mpg depending on output_type.' + #13#10 +
|
||||
'The encoded stream is then decoded and written to a raw data output.' + #13#10 +
|
||||
'output_type must be chosen between "h264", "mp2", "mpg"');
|
||||
Halt;
|
||||
end;
|
||||
output_type := ParamStr(1);
|
||||
if (SameText(output_type, 'h264')) then
|
||||
video_encode_example('test.h264', AV_CODEC_ID_H264)
|
||||
else if (SameText(output_type, 'mp2')) then
|
||||
begin
|
||||
audio_encode_example('test.mp2');
|
||||
audio_decode_example('test.sw', 'test.mp2');
|
||||
end
|
||||
else if (SameText(output_type, 'mpg')) then
|
||||
begin
|
||||
video_encode_example('test.mpg', AV_CODEC_ID_MPEG1VIDEO);
|
||||
video_decode_example('test%02d.pgm', 'test.mpg');
|
||||
end
|
||||
else
|
||||
begin
|
||||
WriteLn(format('Invalid output type "%s", choose between "h264", "mp2", or "mpg"', [output_type]));
|
||||
Halt;
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
WriteLn(E.ClassName, ': ', E.Message);
|
||||
end;
|
||||
|
||||
end.
|
121
samples/FFMpeg/decoding_encoding/decoding_encoding.dproj
Normal file
121
samples/FFMpeg/decoding_encoding/decoding_encoding.dproj
Normal file
@ -0,0 +1,121 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{CE0FA7DD-82F4-40E1-868E-89238AA4468B}</ProjectGuid>
|
||||
<MainSource>decoding_encoding.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<TargetedPlatforms>1</TargetedPlatforms>
|
||||
<AppType>Console</AppType>
|
||||
<FrameworkType>None</FrameworkType>
|
||||
<ProjectVersion>15.4</ProjectVersion>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
|
||||
<Base_Win32>true</Base_Win32>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
|
||||
<Cfg_1>true</Cfg_1>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
|
||||
<Cfg_1_Win32>true</Cfg_1_Win32>
|
||||
<CfgParent>Cfg_1</CfgParent>
|
||||
<Cfg_1>true</Cfg_1>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
|
||||
<Cfg_2>true</Cfg_2>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
|
||||
<Cfg_2_Win32>true</Cfg_2_Win32>
|
||||
<CfgParent>Cfg_2</CfgParent>
|
||||
<Cfg_2>true</Cfg_2>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base)'!=''">
|
||||
<DCC_ExeOutput>..\..\..\bin\$(Platform)</DCC_ExeOutput>
|
||||
<Manifest_File>None</Manifest_File>
|
||||
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
|
||||
<SanitizedProjectName>decoding_encoding</SanitizedProjectName>
|
||||
<DCC_K>false</DCC_K>
|
||||
<VerInfo_Locale>1049</VerInfo_Locale>
|
||||
<DCC_N>false</DCC_N>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=</VerInfo_Keys>
|
||||
<DCC_E>false</DCC_E>
|
||||
<DCC_S>false</DCC_S>
|
||||
<DCC_ImageBase>00400000</DCC_ImageBase>
|
||||
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
|
||||
<DCC_F>false</DCC_F>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||
<DCC_DebugInformation>0</DCC_DebugInformation>
|
||||
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
|
||||
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
|
||||
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<DelphiCompile Include="$(MainSource)">
|
||||
<MainSource>MainSource</MainSource>
|
||||
</DelphiCompile>
|
||||
<BuildConfiguration Include="Debug">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_1</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
||||
<Borland.ProjectType/>
|
||||
<BorlandProject>
|
||||
<Delphi.Personality>
|
||||
<Source>
|
||||
<Source Name="MainSource">decoding_encoding.dpr</Source>
|
||||
</Source>
|
||||
<Excluded_Packages>
|
||||
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k200.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||
<Excluded_Packages Name="$(BDSBIN)\dclofficexp200.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||
</Excluded_Packages>
|
||||
</Delphi.Personality>
|
||||
<Platforms>
|
||||
<Platform value="OSX32">False</Platform>
|
||||
<Platform value="Win32">True</Platform>
|
||||
<Platform value="Win64">False</Platform>
|
||||
</Platforms>
|
||||
</BorlandProject>
|
||||
<ProjectFileVersion>12</ProjectFileVersion>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
|
||||
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
|
||||
</Project>
|
BIN
samples/FFMpeg/decoding_encoding/decoding_encoding.res
Normal file
BIN
samples/FFMpeg/decoding_encoding/decoding_encoding.res
Normal file
Binary file not shown.
@ -34,7 +34,16 @@
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
|
||||
<Cfg_2_Win32>true</Cfg_2_Win32>
|
||||
<CfgParent>Cfg_2</CfgParent>
|
||||
<Cfg_2>true</Cfg_2>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base)'!=''">
|
||||
<DCC_ExeOutput>..\..\..\bin\$(Platform)</DCC_ExeOutput>
|
||||
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
|
||||
<Manifest_File>None</Manifest_File>
|
||||
<DCC_E>false</DCC_E>
|
||||
<VerInfo_Locale>1049</VerInfo_Locale>
|
||||
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
|
||||
@ -58,9 +67,6 @@
|
||||
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
|
||||
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
|
||||
<DCC_ExeOutput>..\..\..\bin\$(Platform)</DCC_ExeOutput>
|
||||
<Manifest_File>None</Manifest_File>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
</PropertyGroup>
|
||||
@ -69,6 +75,10 @@
|
||||
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<DelphiCompile Include="$(MainSource)">
|
||||
<MainSource>MainSource</MainSource>
|
||||
|
@ -230,7 +230,7 @@
|
||||
<DCC_UnitSearchPath>..;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
|
||||
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=OpenCV Component;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=OpenCV Component;ProductVersion=1.0.0.0;Comments=;LastCompiledTime=18.07.2014 0:09:25</VerInfo_Keys>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=OpenCV Component;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=OpenCV Component;ProductVersion=1.0.0.0;Comments=;LastCompiledTime=22.07.2014 15:39:50</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
|
||||
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
|
||||
|
@ -138,7 +138,7 @@
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
||||
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=OpenCV Component;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=OpenCV Component;ProductVersion=1.0.0.0;Comments=;LastCompiledTime=18.07.2014 22:36:06</VerInfo_Keys>
|
||||
<VerInfo_Keys>CompanyName=;FileDescription=OpenCV Component;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=OpenCV Component;ProductVersion=1.0.0.0;Comments=;LastCompiledTime=22.07.2014 15:39:57</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
|
||||
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
|
||||
|
Binary file not shown.
@ -164,6 +164,12 @@ type
|
||||
property OnEndOfFile: TNotifyEvent read FOnEndOfFile Write FOnEndOfFile;
|
||||
end;
|
||||
|
||||
TocvIPProtocol = ( //
|
||||
ippHTTP, //
|
||||
ippHTTPS, //
|
||||
ippRTSP //
|
||||
); //
|
||||
|
||||
TocvIPCamSource = class(TocvCaptureSource)
|
||||
private
|
||||
FPort: Word;
|
||||
@ -171,6 +177,7 @@ type
|
||||
FIP: string;
|
||||
FUserName: String;
|
||||
FURI: string;
|
||||
FProtocol: TocvIPProtocol;
|
||||
protected
|
||||
function GetIPCamTarget: AnsiString;
|
||||
procedure SetEnabled(Value: Boolean); override;
|
||||
@ -182,6 +189,7 @@ type
|
||||
property IP: string read FIP write FIP;
|
||||
property URI: string read FURI write FURI; { TODO: Need rename }
|
||||
property Port: Word read FPort write FPort default 554;
|
||||
property Protocol: TocvIPProtocol read FProtocol write FProtocol default ippRTSP;
|
||||
end;
|
||||
|
||||
TOnNotifyFFMpegPacket = procedure(Sender: TObject; const packet: TAVPacket; const isKeyFrame: Boolean) of object;
|
||||
@ -289,9 +297,9 @@ Type
|
||||
end;
|
||||
|
||||
Const
|
||||
CameraResolution: array [TocvResolution] of TCameraResolution = ((cWidth: 160; cHeight: 120), (cWidth: 320; cHeight: 240),
|
||||
(cWidth: 424; cHeight: 240), (cWidth: 640; cHeight: 360), (cWidth: 800; cHeight: 448), (cWidth: 960; cHeight: 544),
|
||||
(cWidth: 1280; cHeight: 720));
|
||||
CameraResolution: array [TocvResolution] of TCameraResolution = ((cWidth: 160; cHeight: 120), (cWidth: 320;
|
||||
cHeight: 240), (cWidth: 424; cHeight: 240), (cWidth: 640; cHeight: 360), (cWidth: 800; cHeight: 448), (cWidth: 960;
|
||||
cHeight: 544), (cWidth: 1280; cHeight: 720));
|
||||
|
||||
{ TOpenCVCameraThread }
|
||||
|
||||
@ -549,11 +557,19 @@ constructor TocvIPCamSource.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited;
|
||||
FPort := 554;
|
||||
FProtocol := ippRTSP;
|
||||
end;
|
||||
|
||||
function TocvIPCamSource.GetIPCamTarget: AnsiString;
|
||||
const
|
||||
IPProtocolString: array [TocvIPProtocol] of AnsiString = ( //
|
||||
'http://', //
|
||||
'https://', //
|
||||
'rtsp://' //
|
||||
);
|
||||
|
||||
begin
|
||||
Result := 'rtsp://';
|
||||
Result := IPProtocolString[FProtocol];
|
||||
if Length(Trim(UserName)) <> 0 then
|
||||
Result := Result + AnsiString(Trim(UserName)) + ':' + AnsiString(Trim(Password)) + '@';
|
||||
Result := Result + AnsiString(IP) + ':' + AnsiString(IntToStr(Port));
|
||||
@ -839,8 +855,8 @@ begin
|
||||
Continue;
|
||||
end;
|
||||
|
||||
img_convert_context := sws_getCachedContext(nil, pCodecCtx^.Width, pCodecCtx^.Height, pCodecCtx^.pix_fmt, pCodecCtx^.Width,
|
||||
pCodecCtx^.Height, AV_PIX_FMT_BGR24, SWS_BILINEAR, nil, nil, nil);
|
||||
img_convert_context := sws_getCachedContext(nil, pCodecCtx^.Width, pCodecCtx^.Height, pCodecCtx^.pix_fmt,
|
||||
pCodecCtx^.Width, pCodecCtx^.Height, AV_PIX_FMT_BGR24, SWS_BILINEAR, nil, nil, nil);
|
||||
if (img_convert_context = nil) then
|
||||
begin
|
||||
isReconnect := True;
|
||||
@ -866,7 +882,8 @@ begin
|
||||
avcodec_decode_video2(pCodecCtx, frame, frame_finished, @packet);
|
||||
if (frame_finished <> 0) then
|
||||
begin
|
||||
sws_scale(img_convert_context, @frame^.data, @frame^.linesize, 0, pCodecCtx^.Height, @iplframe^.imageData, @linesize);
|
||||
sws_scale(img_convert_context, @frame^.data, @frame^.linesize, 0, pCodecCtx^.Height, @iplframe^.imageData,
|
||||
@linesize);
|
||||
if Assigned(OnNotifyData) then
|
||||
Synchronize(
|
||||
procedure
|
||||
|
@ -45,7 +45,8 @@ uses
|
||||
Graphics,
|
||||
{$ENDIF VER6P}
|
||||
ocv.comp.Types,
|
||||
ocv.core.types_c, System.SyncObjs;
|
||||
ocv.core.types_c,
|
||||
System.SyncObjs;
|
||||
|
||||
type
|
||||
|
||||
|
@ -569,7 +569,8 @@ type
|
||||
* @return the timestamp or AV_NOPTS_VALUE if an error occurred
|
||||
*)
|
||||
// int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit);
|
||||
read_timestamp: function(s: pAVFormatContext; stream_index: Integer; pos: pint64_t; pos_limit: int64_t): int64_t; cdecl;
|
||||
read_timestamp: function(s: pAVFormatContext; stream_index: Integer; pos: pint64_t; pos_limit: int64_t)
|
||||
: int64_t; cdecl;
|
||||
(*
|
||||
* Start/resume playing - only meaningful if using a network-based format
|
||||
* (RTSP).
|
||||
@ -594,8 +595,10 @@ type
|
||||
TAVStreamParseType = ( //
|
||||
AVSTREAM_PARSE_NONE, AVSTREAM_PARSE_FULL, // **< full parsing and repack */
|
||||
AVSTREAM_PARSE_HEADERS, // **< Only parse headers, do not repack. */
|
||||
AVSTREAM_PARSE_TIMESTAMPS, // **< full parsing and interpolation of timestamps for frames not starting on a packet boundary */
|
||||
AVSTREAM_PARSE_FULL_ONCE, // **< full parsing and repack of the first frame only, only implemented for H.264 currently */
|
||||
AVSTREAM_PARSE_TIMESTAMPS,
|
||||
// **< full parsing and interpolation of timestamps for frames not starting on a packet boundary */
|
||||
AVSTREAM_PARSE_FULL_ONCE,
|
||||
// **< full parsing and repack of the first frame only, only implemented for H.264 currently */
|
||||
AVSTREAM_PARSE_FULL_RAW = $57415230 // MKTAG(0,'R','A','W')
|
||||
(* < full parsing and repack with timestamp and position generation by parser for raw
|
||||
this assumes that each packet in the file contains no demuxer level headers and
|
||||
@ -613,7 +616,8 @@ type
|
||||
// int flags:2;
|
||||
// int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).
|
||||
flag_size: int32;
|
||||
min_distance: Integer; (*< Minimum distance between this and the previous keyframe, used to avoid unneeded searching.*)
|
||||
min_distance: Integer;
|
||||
(* < Minimum distance between this and the previous keyframe, used to avoid unneeded searching. *)
|
||||
end;
|
||||
(*
|
||||
* Track should be used during playback by default.
|
||||
@ -1460,8 +1464,8 @@ function avformat_new_stream(s: pAVFormatContext; const c: pAVCodec): pAVStream;
|
||||
* failure
|
||||
*)
|
||||
// int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename);
|
||||
function avformat_alloc_output_context2(Var ctx: pAVFormatContext; oformat: pAVOutputFormat; const format_name: pAnsiChar;
|
||||
const filename: pAnsiChar): Integer; cdecl;
|
||||
function avformat_alloc_output_context2(Var ctx: pAVFormatContext; oformat: pAVOutputFormat;
|
||||
const format_name: pAnsiChar; const filename: pAnsiChar): Integer; cdecl;
|
||||
(*
|
||||
// * @addtogroup lavf_decoding
|
||||
// * @{
|
||||
@ -1550,8 +1554,8 @@ function avformat_alloc_output_context2(Var ctx: pAVFormatContext; oformat: pAVO
|
||||
*)
|
||||
|
||||
// int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);
|
||||
function avformat_open_input(var ps: pAVFormatContext; const filename: pAnsiChar; fmt: pAVInputFormat; options: ppAVDictionary)
|
||||
: Integer; cdecl;
|
||||
function avformat_open_input(var ps: pAVFormatContext; const filename: pAnsiChar; fmt: pAVInputFormat;
|
||||
options: ppAVDictionary): Integer; cdecl;
|
||||
|
||||
// attribute_deprecated
|
||||
// int av_demuxer_open(AVFormatContext *ic);
|
||||
@ -1641,8 +1645,8 @@ function avformat_find_stream_info(ic: pAVFormatContext; options: ppAVDictionary
|
||||
// int related_stream,
|
||||
// AVCodec **decoder_ret,
|
||||
// int flags);
|
||||
function av_find_best_stream(ic: pAVFormatContext; _type: TAVMediaType; wanted_stream_nb: Integer; related_stream: Integer;
|
||||
Var decoder_ret: pAVCodec; flags: Integer): Integer; cdecl;
|
||||
function av_find_best_stream(ic: pAVFormatContext; _type: TAVMediaType; wanted_stream_nb: Integer;
|
||||
related_stream: Integer; Var decoder_ret: pAVCodec; flags: Integer): Integer; cdecl;
|
||||
|
||||
// #if FF_API_READ_PACKET
|
||||
(*
|
||||
@ -1833,7 +1837,7 @@ function avformat_write_header(s: pAVFormatContext; options: ppAVDictionary):Int
|
||||
// * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
|
||||
*)
|
||||
// int av_write_frame(AVFormatContext *s, AVPacket *pkt);
|
||||
//
|
||||
function av_write_frame(s: pAVFormatContext; pkt: pAVPacket): Integer; cdecl;
|
||||
(*
|
||||
// * Write a packet to an output media file ensuring correct interleaving.
|
||||
// *
|
||||
@ -2223,5 +2227,6 @@ function avformat_write_header; external avformat_dll;
|
||||
function av_write_trailer; external avformat_dll;
|
||||
function avformat_new_stream; external avformat_dll;
|
||||
function av_interleaved_write_frame; external avformat_dll;
|
||||
function av_write_frame; external avformat_dll;
|
||||
|
||||
end.
|
||||
|
234
source/ffmpeg/ffm.channel_layout.pas
Normal file
234
source/ffmpeg/ffm.channel_layout.pas
Normal file
@ -0,0 +1,234 @@
|
||||
(*
|
||||
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
* Copyright (c) 2008 Peter Ross
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*)
|
||||
|
||||
unit ffm.channel_layout;
|
||||
|
||||
{$i ffmpeg.inc}
|
||||
|
||||
interface
|
||||
|
||||
Uses
|
||||
ffm.ctypes;
|
||||
|
||||
(* *
|
||||
* @file
|
||||
* audio channel layout utility functions
|
||||
*)
|
||||
|
||||
(* *
|
||||
* @addtogroup lavu_audio
|
||||
* @{
|
||||
*)
|
||||
|
||||
(* *
|
||||
* @defgroup channel_masks Audio channel masks
|
||||
*
|
||||
* A channel layout is a 64-bits integer with a bit set for every channel.
|
||||
* The number of bits set must be equal to the number of channels.
|
||||
* The value 0 means that the channel layout is not known.
|
||||
* @note this data structure is not powerful enough to handle channels
|
||||
* combinations that have the same channel multiple times, such as
|
||||
* dual-mono.
|
||||
*
|
||||
* @{
|
||||
*)
|
||||
Const
|
||||
AV_CH_FRONT_LEFT = $00000001;
|
||||
AV_CH_FRONT_RIGHT = $00000002;
|
||||
AV_CH_FRONT_CENTER = $00000004;
|
||||
AV_CH_LOW_FREQUENCY = $00000008;
|
||||
AV_CH_BACK_LEFT = $00000010;
|
||||
AV_CH_BACK_RIGHT = $00000020;
|
||||
AV_CH_FRONT_LEFT_OF_CENTER = $00000040;
|
||||
AV_CH_FRONT_RIGHT_OF_CENTER = $00000080;
|
||||
AV_CH_BACK_CENTER = $00000100;
|
||||
AV_CH_SIDE_LEFT = $00000200;
|
||||
AV_CH_SIDE_RIGHT = $00000400;
|
||||
AV_CH_TOP_CENTER = $00000800;
|
||||
AV_CH_TOP_FRONT_LEFT = $00001000;
|
||||
AV_CH_TOP_FRONT_CENTER = $00002000;
|
||||
AV_CH_TOP_FRONT_RIGHT = $00004000;
|
||||
AV_CH_TOP_BACK_LEFT = $00008000;
|
||||
AV_CH_TOP_BACK_CENTER = $00010000;
|
||||
AV_CH_TOP_BACK_RIGHT = $00020000;
|
||||
AV_CH_STEREO_LEFT = $20000000;
|
||||
/// < Stereo downmix.
|
||||
AV_CH_STEREO_RIGHT = $40000000;
|
||||
/// < See AV_CH_STEREO_LEFT.
|
||||
AV_CH_WIDE_LEFT = $0000000080000000;
|
||||
AV_CH_WIDE_RIGHT = $0000000100000000;
|
||||
AV_CH_SURROUND_DIRECT_LEFT = $0000000200000000;
|
||||
AV_CH_SURROUND_DIRECT_RIGHT = $0000000400000000;
|
||||
AV_CH_LOW_FREQUENCY_2 = $0000000800000000;
|
||||
|
||||
(* * Channel mask value used for AVCodecContext.request_channel_layout
|
||||
to indicate that the user requests the channel order of the decoder output
|
||||
to be the native codec channel order. *)
|
||||
AV_CH_LAYOUT_NATIVE = $8000000000000000;
|
||||
|
||||
(* *
|
||||
* @}
|
||||
* @defgroup channel_mask_c Audio channel convenience macros
|
||||
* @{
|
||||
* *)
|
||||
AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER);
|
||||
AV_CH_LAYOUT_STEREO = (AV_CH_FRONT_LEFT or AV_CH_FRONT_RIGHT);
|
||||
AV_CH_LAYOUT_2POINT1 = (AV_CH_LAYOUT_STEREO or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_2_1 = (AV_CH_LAYOUT_STEREO or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_SURROUND = (AV_CH_LAYOUT_STEREO or AV_CH_FRONT_CENTER);
|
||||
AV_CH_LAYOUT_3POINT1 = (AV_CH_LAYOUT_SURROUND or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_4POINT0 = (AV_CH_LAYOUT_SURROUND or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_4POINT1 = (AV_CH_LAYOUT_4POINT0 or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_2_2 = (AV_CH_LAYOUT_STEREO or AV_CH_SIDE_LEFT or AV_CH_SIDE_RIGHT);
|
||||
AV_CH_LAYOUT_QUAD = (AV_CH_LAYOUT_STEREO or AV_CH_BACK_LEFT or AV_CH_BACK_RIGHT);
|
||||
AV_CH_LAYOUT_5POINT0 = (AV_CH_LAYOUT_SURROUND or AV_CH_SIDE_LEFT or AV_CH_SIDE_RIGHT);
|
||||
AV_CH_LAYOUT_5POINT1 = (AV_CH_LAYOUT_5POINT0 or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_5POINT0_BACK = (AV_CH_LAYOUT_SURROUND or AV_CH_BACK_LEFT or AV_CH_BACK_RIGHT);
|
||||
AV_CH_LAYOUT_5POINT1_BACK = (AV_CH_LAYOUT_5POINT0_BACK or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_6POINT0 = (AV_CH_LAYOUT_5POINT0 or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_6POINT0_FRONT = (AV_CH_LAYOUT_2_2 or AV_CH_FRONT_LEFT_OF_CENTER or AV_CH_FRONT_RIGHT_OF_CENTER);
|
||||
AV_CH_LAYOUT_HEXAGONAL = (AV_CH_LAYOUT_5POINT0_BACK or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_6POINT1 = (AV_CH_LAYOUT_5POINT1 or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_6POINT1_BACK = (AV_CH_LAYOUT_5POINT1_BACK or AV_CH_BACK_CENTER);
|
||||
AV_CH_LAYOUT_6POINT1_FRONT = (AV_CH_LAYOUT_6POINT0_FRONT or AV_CH_LOW_FREQUENCY);
|
||||
AV_CH_LAYOUT_7POINT0 = (AV_CH_LAYOUT_5POINT0 or AV_CH_BACK_LEFT or AV_CH_BACK_RIGHT);
|
||||
AV_CH_LAYOUT_7POINT0_FRONT = (AV_CH_LAYOUT_5POINT0 or AV_CH_FRONT_LEFT_OF_CENTER or AV_CH_FRONT_RIGHT_OF_CENTER);
|
||||
AV_CH_LAYOUT_7POINT1 = (AV_CH_LAYOUT_5POINT1 or AV_CH_BACK_LEFT or AV_CH_BACK_RIGHT);
|
||||
AV_CH_LAYOUT_7POINT1_WIDE = (AV_CH_LAYOUT_5POINT1 or AV_CH_FRONT_LEFT_OF_CENTER or AV_CH_FRONT_RIGHT_OF_CENTER);
|
||||
AV_CH_LAYOUT_7POINT1_WIDE_BACK = (AV_CH_LAYOUT_5POINT1_BACK or AV_CH_FRONT_LEFT_OF_CENTER or
|
||||
AV_CH_FRONT_RIGHT_OF_CENTER);
|
||||
AV_CH_LAYOUT_OCTAGONAL = (AV_CH_LAYOUT_5POINT0 or AV_CH_BACK_LEFT or AV_CH_BACK_CENTER or AV_CH_BACK_RIGHT);
|
||||
AV_CH_LAYOUT_STEREO_DOWNMIX = (AV_CH_STEREO_LEFT or AV_CH_STEREO_RIGHT);
|
||||
|
||||
Type
|
||||
TAVMatrixEncoding = ( //
|
||||
AV_MATRIX_ENCODING_NONE, //
|
||||
AV_MATRIX_ENCODING_DOLBY, //
|
||||
AV_MATRIX_ENCODING_DPLII, //
|
||||
AV_MATRIX_ENCODING_DPLIIX, //
|
||||
AV_MATRIX_ENCODING_DPLIIZ, //
|
||||
AV_MATRIX_ENCODING_DOLBYEX, //
|
||||
AV_MATRIX_ENCODING_DOLBYHEADPHONE, //
|
||||
AV_MATRIX_ENCODING_NB);
|
||||
|
||||
(* *
|
||||
* @}
|
||||
*)
|
||||
|
||||
(* *
|
||||
* Return a channel layout id that matches name, or 0 if no match is found.
|
||||
*
|
||||
* name can be one or several of the following notations,
|
||||
* separated by '+' or ' or ':
|
||||
* - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0,
|
||||
* 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);
|
||||
* - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,
|
||||
* SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);
|
||||
* - a number of channels, in decimal, optionally followed by 'c', yielding
|
||||
* the default channel layout for that number of channels (@see
|
||||
* av_get_default_channel_layout);
|
||||
* - a channel layout mask, in hexadecimal starting with "$" (see the
|
||||
* AV_CH_* macros).
|
||||
*
|
||||
* @warning Starting from the next major bump the trailing character
|
||||
* 'c' to specify a number of channels will be required, while a
|
||||
* channel layout mask could also be specified as a decimal number
|
||||
* (if and only if not followed by "c").
|
||||
*
|
||||
* Example: "stereo+FC" = "2c+FC" = "2c+1c" = "$7"
|
||||
*)
|
||||
// uint64_t av_get_channel_layout(const char *name);
|
||||
|
||||
(* *
|
||||
* Return a description of a channel layout.
|
||||
* If nb_channels is <= 0, it is guessed from the channel_layout.
|
||||
*
|
||||
* @param buf put here the string containing the channel layout
|
||||
* @param buf_size size in bytes of the buffer
|
||||
*)
|
||||
// void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);
|
||||
|
||||
// struct AVBPrint;
|
||||
(* *
|
||||
* Append a description of a channel layout to a bprint buffer.
|
||||
*)
|
||||
// void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout);
|
||||
|
||||
(* *
|
||||
* Return the number of channels in the channel layout.
|
||||
*)
|
||||
// int av_get_channel_layout_nb_channels(uint64_t channel_layout);
|
||||
function av_get_channel_layout_nb_channels(channel_layout: uint64_t): Integer; cdecl;
|
||||
|
||||
(* *
|
||||
* Return default channel layout for a given number of channels.
|
||||
*)
|
||||
// int64_t av_get_default_channel_layout(int nb_channels);
|
||||
|
||||
(* *
|
||||
* Get the index of a channel in channel_layout.
|
||||
*
|
||||
* @param channel a channel layout describing exactly one channel which must be
|
||||
* present in channel_layout.
|
||||
*
|
||||
* @return index of channel in channel_layout on success, a negative AVERROR
|
||||
* on error.
|
||||
*)
|
||||
// int av_get_channel_layout_channel_index(uint64_t channel_layout,uint64_t channel);
|
||||
|
||||
(* *
|
||||
* Get the channel with the given index in channel_layout.
|
||||
*)
|
||||
// uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);
|
||||
|
||||
(* *
|
||||
* Get the name of a given channel.
|
||||
*
|
||||
* @return channel name on success, NULL on error.
|
||||
*)
|
||||
// const char *av_get_channel_name(uint64_t channel);
|
||||
|
||||
(* *
|
||||
* Get the description of a given channel.
|
||||
*
|
||||
* @param channel a channel layout with a single channel
|
||||
* @return channel description on success, NULL on error
|
||||
*)
|
||||
// const char *av_get_channel_description(uint64_t channel);
|
||||
|
||||
(* *
|
||||
* Get the value and name of a standard channel layout.
|
||||
*
|
||||
* @param[in] index index in an internal list, starting at 0
|
||||
* @param[out] layout channel layout mask
|
||||
* @param[out] name name of the layout
|
||||
* @return 0 if the layout exists,
|
||||
* <0 if index is beyond the limits
|
||||
*)
|
||||
// int av_get_standard_channel_layout(unsigned index, uint64_t *layout, const char **name);
|
||||
|
||||
implementation
|
||||
|
||||
uses ffm.lib;
|
||||
|
||||
function av_get_channel_layout_nb_channels; external channel_layout_dll;
|
||||
|
||||
end.
|
@ -46,6 +46,9 @@ Type
|
||||
nAudioBufferSizeCurrent: Integer;
|
||||
W_VIDEO: Integer;
|
||||
H_VIDEO: Integer;
|
||||
fbit_rate: Integer;
|
||||
ftime_base_den: Integer;
|
||||
function flush_encoder: Integer;
|
||||
protected
|
||||
// Add video stream
|
||||
function AddVideoStream(const pContext: pAVFormatContext; const codec_id: TAVCodecID): pAVStream;
|
||||
@ -75,6 +78,8 @@ Type
|
||||
// init output file
|
||||
function InitFile(const inputFile: AnsiString; const container: AnsiString; const AW_VIDEO: Integer = 320;
|
||||
const AH_VIDEO: Integer = 200): boolean;
|
||||
// Set video params
|
||||
procedure SetVideoParams(const atime_base_den: Integer = 25; const abit_rate: Integer = 2000000);
|
||||
// Add video and audio data
|
||||
function AddFrame(const frame: pAVFrame; const soundBuffer: pByte; const soundBufferSize: Integer;
|
||||
const framepixfmt: TAVPixelFormat = AV_PIX_FMT_RGB24): boolean;
|
||||
@ -312,6 +317,7 @@ begin
|
||||
|
||||
// Write packet with frame.
|
||||
Result := av_interleaved_write_frame(pFormatContext, @pkt) = 0;
|
||||
// Result := av_write_frame(pFormatContext, @pkt) = 0;
|
||||
end
|
||||
else
|
||||
Result := false;
|
||||
@ -322,7 +328,6 @@ function TFFMVideoEncoder.AddVideoStream(const pContext: pAVFormatContext; const
|
||||
Var
|
||||
pCodecCxt: pAVCodecContext;
|
||||
begin
|
||||
|
||||
pCodecCxt := nil;
|
||||
Result := nil;
|
||||
|
||||
@ -338,7 +343,7 @@ begin
|
||||
pCodecCxt^.codec_type := AVMEDIA_TYPE_VIDEO;
|
||||
pCodecCxt^.frame_number := 0;
|
||||
// Put sample parameters.
|
||||
pCodecCxt^.bit_rate := 2000000;
|
||||
pCodecCxt^.bit_rate := fbit_rate; // 2000000;
|
||||
// Resolution must be a multiple of two.
|
||||
pCodecCxt^.width := W_VIDEO;
|
||||
pCodecCxt^.height := H_VIDEO;
|
||||
@ -346,7 +351,7 @@ begin
|
||||
of which frame timestamps are represented. for fixed-fps content,
|
||||
timebase should be 1/framerate and timestamp increments should be
|
||||
identically 1. *)
|
||||
pCodecCxt^.time_base.den := 25;
|
||||
pCodecCxt^.time_base.den := ftime_base_den; // 25;
|
||||
pCodecCxt^.time_base.num := 1;
|
||||
pCodecCxt^.gop_size := 12; // emit one intra frame every twelve frames at most
|
||||
|
||||
@ -418,6 +423,7 @@ begin
|
||||
nAudioBufferSize := 1024 * 1024 * 4;
|
||||
audioBuffer := AllocMem(nAudioBufferSize);
|
||||
nAudioBufferSizeCurrent := 0;
|
||||
SetVideoParams;
|
||||
end;
|
||||
|
||||
function TFFMVideoEncoder.CreateFFmpegPicture(const pix_fmt: TAVPixelFormat; const nWidth, nHeight: Integer): pAVFrame;
|
||||
@ -458,6 +464,7 @@ begin
|
||||
// Todo: Maybe you need write audio samples from audioBuffer to file before cloasing.
|
||||
if Assigned(pFormatContext) then
|
||||
begin
|
||||
// flush_encoder;
|
||||
av_write_trailer(pFormatContext);
|
||||
Free;
|
||||
end;
|
||||
@ -469,6 +476,32 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TFFMVideoEncoder.flush_encoder: Integer;
|
||||
Var
|
||||
ret, got_output: Integer;
|
||||
pkt: TAVPacket;
|
||||
begin
|
||||
(* get the delayed frames *)
|
||||
av_init_packet(@pkt);
|
||||
got_output := 1;
|
||||
While got_output <> 0 do
|
||||
begin
|
||||
ret := avcodec_encode_video2(pVideoStream^.codec, @pkt, nil, got_output);
|
||||
if (ret < 0) then
|
||||
begin
|
||||
// WriteLn('Error encoding frame');
|
||||
Exit(ret);
|
||||
end;
|
||||
if (got_output <> 0) then
|
||||
begin
|
||||
// WriteLn(format('Write frame %3d (size=%5d)', [i, pkt.size]));
|
||||
// BlockWrite(f, pkt.data^, pkt.size);
|
||||
av_free_packet(pkt);
|
||||
end;
|
||||
// Inc(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFFMVideoEncoder.Free;
|
||||
Var
|
||||
i: Integer;
|
||||
@ -542,8 +575,8 @@ begin
|
||||
if Assigned(pAudioStream) then
|
||||
Result := OpenAudio(pFormatContext, pAudioStream);
|
||||
|
||||
if Result and ((pOutFormat^.flags and AVFMT_NOFILE) = 0) and (avio_open(pFormatContext^.pb, filename, AVIO_FLAG_WRITE) < 0)
|
||||
then
|
||||
if Result and ((pOutFormat^.flags and AVFMT_NOFILE) = 0) and
|
||||
(avio_open(pFormatContext^.pb, filename, AVIO_FLAG_WRITE) < 0) then
|
||||
begin
|
||||
Result := false;
|
||||
// printf(" Cannot open file\ n ");
|
||||
@ -639,4 +672,10 @@ begin
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
procedure TFFMVideoEncoder.SetVideoParams(const atime_base_den, abit_rate: Integer);
|
||||
begin
|
||||
fbit_rate := abit_rate;
|
||||
ftime_base_den := atime_base_den;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -136,6 +136,9 @@ Type
|
||||
pAVBufferRefArray = ^TAVBufferRefArray;
|
||||
TAVBufferRefArray = array [0 .. AV_NUM_DATA_POINTERS - 1] of pAVBufferRef;
|
||||
|
||||
TLinesizes = array [0 .. AV_NUM_DATA_POINTERS - 1] of Integer;
|
||||
pLinesizes = ^TLinesizes;
|
||||
|
||||
TAVFrame = {packed} record
|
||||
(*
|
||||
* pointer to the picture/channel planes.
|
||||
@ -162,7 +165,7 @@ Type
|
||||
* @note The linesize may be larger than the size of usable data -- there
|
||||
* may be extra padding present for performance reasons.
|
||||
*)
|
||||
linesize: array [0 .. AV_NUM_DATA_POINTERS - 1] of Integer;
|
||||
linesize: TLinesizes;
|
||||
(*
|
||||
* pointers to the data planes/channels.
|
||||
*
|
||||
|
@ -5,7 +5,7 @@ unit ffm.imgutils;
|
||||
interface
|
||||
|
||||
uses
|
||||
ffm.pixfmt;
|
||||
ffm.pixfmt, ffm.frame;
|
||||
|
||||
(*
|
||||
* This file is part of ffm.
|
||||
@ -87,14 +87,16 @@ uses
|
||||
*)
|
||||
// int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
|
||||
// int w, int h, enum AVPixelFormat pix_fmt, int align);
|
||||
Type
|
||||
TPointers = array [0 .. 3] of pByte;
|
||||
pPointers = ^TPointers;
|
||||
TLinesizes = array [0 .. 3] of integer;
|
||||
pLinesizes = ^TLinesizes;
|
||||
// Type
|
||||
// TPointers = array [0 .. 3] of pByte;
|
||||
// pPointers = ^TPointers;
|
||||
// TLinesizes = array [0 .. 3] of integer;
|
||||
// pLinesizes = ^TLinesizes;
|
||||
|
||||
function av_image_alloc(Var pointers: TPointers; linesizes: TLinesizes; w: integer; h: integer; pix_fmt: TAVPixelFormat;
|
||||
align: integer): integer; cdecl;
|
||||
function av_image_alloc(Var pointers: TAVFrameByteArray; linesizes: TLinesizes; w: integer; h: integer;
|
||||
pix_fmt: TAVPixelFormat; align: integer): integer; cdecl;
|
||||
// function av_image_alloc(pointers: pPointers; linesizes: TLinesizes; w: integer; h: integer; pix_fmt: TAVPixelFormat;
|
||||
// align: integer): integer; overload; cdecl;
|
||||
|
||||
(*
|
||||
* Copy image plane from src to dst.
|
||||
@ -200,5 +202,9 @@ implementation
|
||||
uses ffm.lib;
|
||||
|
||||
function av_image_alloc; external avutil_dll;
|
||||
// function av_image_alloc(Var pointers: TPointers; linesizes: TLinesizes; w: integer; h: integer; pix_fmt: TAVPixelFormat;
|
||||
// align: integer): integer; overload; cdecl; external avutil_dll name 'av_image_alloc';
|
||||
// function av_image_alloc(pointers: pPointers; linesizes: TLinesizes; w: integer; h: integer; pix_fmt: TAVPixelFormat;
|
||||
// align: integer): integer; overload; cdecl; external avutil_dll name 'av_image_alloc';
|
||||
|
||||
end.
|
||||
|
@ -12,6 +12,7 @@ const
|
||||
avfilter_dll = 'avfilter-4.dll';
|
||||
avio_dll = avformat_dll;
|
||||
samplefmt_dll = avutil_dll;
|
||||
channel_layout_dll=avutil_dll;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -730,7 +730,8 @@ Type
|
||||
// AV_CODEC_ID_SMPTE_KLV = $4B4C5641, // MKBETAG('K','L','V','A'),
|
||||
// AV_CODEC_ID_DVD_NAV = $444E4156, // MKBETAG('D','N','A','V'),
|
||||
|
||||
AV_CODEC_ID_PROBE = $19000, // < codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
|
||||
AV_CODEC_ID_PROBE = $19000,
|
||||
// < codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
|
||||
|
||||
AV_CODEC_ID_MPEG2TS = $20000, // **< _FAKE_ codec to indicate a raw MPEG-2 TS
|
||||
// * stream (only used by libavformat) *)
|
||||
@ -1528,8 +1529,8 @@ Type
|
||||
|
||||
// int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size);
|
||||
TExecuteFunc = function(c2: pAVCodecContext; arg: pointer): Integer; cdecl;
|
||||
TExecute = function(c: pAVCodecContext; ExecuteFunc: TExecuteFunc; arg2: pointer; ret: PInteger; count: Integer; size: Integer)
|
||||
: Integer; cdecl;
|
||||
TExecute = function(c: pAVCodecContext; ExecuteFunc: TExecuteFunc; arg2: pointer; ret: PInteger; count: Integer;
|
||||
size: Integer): Integer; cdecl;
|
||||
|
||||
// int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count);
|
||||
TExecuteFunc2 = function(c2: pAVCodecContext; arg: pointer; jobnr: Integer; threadnr: Integer): Integer; cdecl;
|
||||
@ -2850,7 +2851,8 @@ Type
|
||||
* - decoding: Set by libavcodec, user can override.
|
||||
*)
|
||||
// int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size);
|
||||
execute: function(c: pAVCodecContext; func: TExecuteFunc; arg2: pointer; Var ret: cint; count: cint; size: cint): cint; cdecl;
|
||||
execute: function(c: pAVCodecContext; func: TExecuteFunc; arg2: pointer; Var ret: cint; count: cint; size: cint)
|
||||
: cint; cdecl;
|
||||
|
||||
(*
|
||||
* The codec may call this to execute several independent things.
|
||||
@ -3955,9 +3957,9 @@ function avcodec_find_decoder(id: TAVCodecID): pAVCodec; cdecl;
|
||||
* decoding, otherwise the number of bytes consumed from the input
|
||||
* AVPacket is returned.
|
||||
*)
|
||||
// int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
|
||||
// int *got_frame_ptr, const AVPacket *avpkt);
|
||||
//
|
||||
// int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, const AVPacket *avpkt);
|
||||
function avcodec_decode_audio4(avctx: pAVCodecContext; frame: pAVFrame; var got_frame_ptr: Integer;
|
||||
const avpkt: pAVPacket):Integer; cdecl;
|
||||
(*
|
||||
* Decode the video frame of size avpkt->size from avpkt->data into picture.
|
||||
* Some decoders may support multiple frames in a single AVPacket, such
|
||||
@ -4195,8 +4197,8 @@ Type
|
||||
// AVCodecContext *avctx,
|
||||
// const uint8_t **poutbuf, int *poutbuf_size,
|
||||
// const uint8_t *buf, int buf_size);
|
||||
parser_parse: function(s: pAVCodecParserContext; avctx: pAVCodecContext; const poutbuf: ppByte; poutbuf_size: PInteger;
|
||||
const buf: pByte; buf_size: Integer): Integer; cdecl;
|
||||
parser_parse: function(s: pAVCodecParserContext; avctx: pAVCodecContext; const poutbuf: ppByte;
|
||||
poutbuf_size: PInteger; const buf: pByte; buf_size: Integer): Integer; cdecl;
|
||||
// void (*parser_close)(AVCodecParserContext *s);
|
||||
parser_close: procedure(s: pAVCodecParserContext); cdecl;
|
||||
// int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
|
||||
@ -4341,8 +4343,8 @@ function avcodec_find_encoder(id: TAVCodecID): pAVCodec; cdecl;
|
||||
*)
|
||||
// int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
// const AVFrame *frame, int *got_packet_ptr);
|
||||
function avcodec_encode_audio2(avctx: pAVCodecContext; avpkt: pAVPacket; const frame: pAVFrame; Var got_packet_ptr: Integer)
|
||||
: Integer; cdecl;
|
||||
function avcodec_encode_audio2(avctx: pAVCodecContext; avpkt: pAVPacket; const frame: pAVFrame;
|
||||
Var got_packet_ptr: Integer): Integer; cdecl;
|
||||
|
||||
// #if FF_API_OLD_ENCODE_VIDEO
|
||||
(*
|
||||
@ -4400,8 +4402,8 @@ function avcodec_encode_audio2(avctx: pAVCodecContext; avpkt: pAVPacket; const f
|
||||
*)
|
||||
// int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
// const AVFrame *frame, int *got_packet_ptr);
|
||||
function avcodec_encode_video2(avctx: pAVCodecContext; avpkt: pAVPacket; const frame: pAVFrame; Var got_packet_ptr: Integer)
|
||||
: Integer; cdecl;
|
||||
function avcodec_encode_video2(avctx: pAVCodecContext; avpkt: pAVPacket; const frame: pAVFrame;
|
||||
Var got_packet_ptr: Integer): Integer; cdecl;
|
||||
|
||||
// int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
|
||||
// const AVSubtitle *sub);
|
||||
@ -4811,7 +4813,8 @@ function avcodec_fill_audio_frame(frame: pAVFrame; nb_channels: Integer; sample_
|
||||
// * keep internally, but the caller's reference remains valid.
|
||||
*)
|
||||
// void avcodec_flush_buffers(AVCodecContext *avctx);
|
||||
//
|
||||
procedure avcodec_flush_buffers(avctx: pAVCodecContext); cdecl;
|
||||
|
||||
(*
|
||||
// * Return codec bits per sample.
|
||||
// *
|
||||
@ -5125,5 +5128,7 @@ function avcodec_find_encoder; external avcodec_dll;
|
||||
function avcodec_encode_video2; external avcodec_dll;
|
||||
function avcodec_fill_audio_frame; external avcodec_dll;
|
||||
function avcodec_encode_audio2; external avcodec_dll;
|
||||
procedure avcodec_flush_buffers; external avcodec_dll;
|
||||
function avcodec_decode_audio4; external avcodec_dll;
|
||||
|
||||
end.
|
||||
|
@ -234,7 +234,8 @@ Type
|
||||
{ } AV_OPT_TYPE_BINARY,
|
||||
// < offset must point to a pointer immediately followed by an int for the length
|
||||
{ } AV_OPT_TYPE_CONST = 128,
|
||||
{ } AV_OPT_TYPE_IMAGE_SIZE = $53495A45, // MKBETAG('S', 'I', 'Z', 'E'), // < offset must point to two consecutive integers
|
||||
{ } AV_OPT_TYPE_IMAGE_SIZE = $53495A45,
|
||||
// MKBETAG('S', 'I', 'Z', 'E'), // < offset must point to two consecutive integers
|
||||
{ } AV_OPT_TYPE_PIXEL_FMT = $50464D54, // MKBETAG('P', 'F', 'M', 'T'),
|
||||
{ } AV_OPT_TYPE_SAMPLE_FMT = $53464D54, // MKBETAG('S', 'F', 'M', 'T'),
|
||||
{ } AV_OPT_TYPE_VIDEO_RATE = $56524154, // MKBETAG('V', 'R', 'A', 'T'), // < offset must point to AVRational
|
||||
@ -674,11 +675,13 @@ const
|
||||
// * AVERROR(EINVAL) if the value is not valid
|
||||
// */
|
||||
// int av_opt_set (void *obj, const char *name, const char *val, int search_flags);
|
||||
function av_opt_set(obj: Pointer; const name: pAnsiChar; const val: pAnsiChar; search_flags: Integer): Integer; cdecl;
|
||||
// int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags);
|
||||
// int av_opt_set_double(void *obj, const char *name, double val, int search_flags);
|
||||
// int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags);
|
||||
// int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags);
|
||||
function av_opt_set_bin(obj: Pointer; const name: pAnsiChar; const val: PByte; size: Integer; search_flags: Integer):Integer; cdecl;
|
||||
function av_opt_set_bin(obj: Pointer; const name: pAnsiChar; const val: PByte; size: Integer; search_flags: Integer)
|
||||
: Integer; cdecl;
|
||||
// int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags);
|
||||
// int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags);
|
||||
// int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags);
|
||||
@ -784,5 +787,6 @@ implementation
|
||||
uses ffm.lib;
|
||||
|
||||
function av_opt_set_bin; external avutil_dll;
|
||||
function av_opt_set; external avutil_dll;
|
||||
|
||||
end.
|
||||
|
@ -45,7 +45,8 @@ interface
|
||||
*)
|
||||
Type
|
||||
pAVSampleFormat = ^TAVSampleFormat;
|
||||
TAVSampleFormat = (AV_SAMPLE_FMT_NONE = -1, //
|
||||
TAVSampleFormat = ( //
|
||||
AV_SAMPLE_FMT_NONE = -1, //
|
||||
AV_SAMPLE_FMT_U8,
|
||||
/// < unsigned 8 bits
|
||||
AV_SAMPLE_FMT_S16,
|
||||
@ -56,7 +57,6 @@ Type
|
||||
/// < float
|
||||
AV_SAMPLE_FMT_DBL,
|
||||
/// < double
|
||||
|
||||
AV_SAMPLE_FMT_U8P,
|
||||
/// < unsigned 8 bits, planar
|
||||
AV_SAMPLE_FMT_S16P,
|
||||
@ -67,7 +67,6 @@ Type
|
||||
/// < float, planar
|
||||
AV_SAMPLE_FMT_DBLP,
|
||||
/// < double, planar
|
||||
|
||||
AV_SAMPLE_FMT_NB
|
||||
/// < Number of sample formats. DO NOT USE if linking dynamically
|
||||
);
|
||||
@ -77,6 +76,7 @@ Type
|
||||
* recognized.
|
||||
*)
|
||||
// const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt);
|
||||
function av_get_sample_fmt_name(sample_fmt: TAVSampleFormat): pAnsiChar; cdecl;
|
||||
|
||||
(*
|
||||
* Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE
|
||||
@ -163,8 +163,9 @@ function av_get_bytes_per_sample(sample_fmt: TAVSampleFormat): integer; cdecl;
|
||||
* @param align buffer size alignment (0 = default, 1 = no alignment)
|
||||
* @return required buffer size, or negative error code on failure
|
||||
*)
|
||||
// int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
|
||||
// enum AVSampleFormat sample_fmt, int align);
|
||||
// int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align);
|
||||
function av_samples_get_buffer_size(linesize: pInteger; nb_channels: integer; nb_samples: integer;
|
||||
sample_fmt: TAVSampleFormat; align: integer): integer; cdecl;
|
||||
|
||||
(*
|
||||
* Fill plane data pointers and linesize for samples with sample
|
||||
@ -267,5 +268,7 @@ implementation
|
||||
uses ffm.lib;
|
||||
|
||||
function av_get_bytes_per_sample; external samplefmt_dll;
|
||||
function av_get_sample_fmt_name; external samplefmt_dll;
|
||||
function av_samples_get_buffer_size; external samplefmt_dll;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user