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

197 lines
4.9 KiB
ObjectPascal
Raw Normal View History

program ffmpeg_sample_player;
{ .$APPTYPE CONSOLE }
{$R *.res}
{$include ffmpeg.inc}
uses
Winapi.Windows,
System.SysUtils,
System.Classes,
SDL,
ffmpeglib,
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,
ffmpeg.avfilter,
ffmpeg.buffersink,
ffmpeg.mathematics,
ffmpeg.libavcodec.avcodec,
ffmpeg.buffersrc,
ffmpeg.errno,
uResourcePaths;
var
err: Integer;
filename: AnsiString;
format_context: pAVFormatContext = nil;
video_stream: Integer;
codec_context: pAVCodecContext;
codec: pAVCodec;
screen: pSDL_Surface;
bmp: pSDL_Overlay;
img_convert_context: pSwsContext;
frame: pAVFrame;
packet: TAVPacket;
frame_finished: Integer;
pict: TAVPicture;
rect: TSDL_Rect;
event: TSDL_Event;
const
std_filename = cResourceMedia + 'trailer.avi';
begin
try
if (ParamCount < 1) then
filename := std_filename
else
filename := ParamStr(1);
// Register all available file formats and codecs
av_register_all();
avformat_network_init();
// Init SDL with video support
err := SDL_Init(SDL_INIT_VIDEO);
if (err < 0) then
begin
WriteLn(Format('Unable to init SDL: %s', [SDL_GetError()]));
Halt(1);
end;
// Open video file
err := avformat_open_input(format_context, PAnsiChar(filename), nil, nil);
if (err < 0) then
begin
WriteLn('ffmpeg: Unable to open input file');
Halt(1);
end;
// Retrieve stream information
err := avformat_find_stream_info(format_context, nil);
if (err < 0) then
begin
WriteLn('ffmpeg: Unable to find stream info');
Halt(1);
end;
// Dump information about file onto standard error
av_dump_format(format_context, 0, PAnsiChar(filename), 0);
// Find the first video stream
for video_stream := 0 to format_context^.nb_streams - 1 do
if (format_context^.streams[video_stream]^.codec^.codec_type = AVMEDIA_TYPE_VIDEO) then
break;
if (video_stream = format_context^.nb_streams) then
begin
WriteLn('ffmpeg: Unable to find video stream');
Halt(1);
end;
codec_context := format_context^.streams[video_stream]^.codec;
codec := avcodec_find_decoder(codec_context^.codec_id);
err := avcodec_open2(codec_context, codec, nil);
if (err < 0) then
begin
WriteLn('ffmpeg: Unable to open codec');
Halt(1);
end;
screen := SDL_SetVideoMode(codec_context^.width, codec_context^.height, 0, 0 { SDL_FULLSCREEN } );
if (screen = nil) then
begin
WriteLn('Couldn''t set video mode');
Halt(1);
end;
bmp := SDL_CreateYUVOverlay(codec_context^.width, codec_context^.height, SDL_YV12_OVERLAY, screen);
img_convert_context := sws_getCachedContext(nil, codec_context^.width, codec_context^.height, codec_context^.pix_fmt, codec_context^.width, codec_context^.height, AV_PIX_FMT_YUV420P, SWS_BICUBIC,
nil, nil, nil);
if (img_convert_context = nil) then
begin
WriteLn('Cannot initialize the conversion context');
Halt(1);
end;
frame := avcodec_alloc_frame();
while (av_read_frame(format_context, packet) >= 0) do
begin
if (packet.stream_index = video_stream) then
begin
// Video stream packet
avcodec_decode_video2(codec_context, frame, frame_finished, @packet);
if (frame_finished <> 0) then
begin
SDL_LockYUVOverlay(bmp);
// Convert frame to YV12 pixel format for display in SDL overlay
pByte(pict.data[0]) := pByte(bmp^.pixels[0]);
pByte(pict.data[1]) := pByte(bmp^.pixels[2]); // it's because YV12
pByte(pict.data[2]) := pByte(bmp^.pixels[1]);
pict.linesize[0] := bmp^.pitches[0];
pict.linesize[1] := bmp^.pitches[2];
pict.linesize[2] := bmp^.pitches[1];
sws_scale(img_convert_context, @frame^.data, @frame^.linesize, 0, codec_context^.height, @pict.data, @pict.linesize);
SDL_UnlockYUVOverlay(bmp);
rect.x := 0;
rect.y := 0;
rect.w := codec_context^.width;
rect.h := codec_context^.height;
SDL_DisplayYUVOverlay(bmp, @rect);
end;
end;
// Free the packet that was allocated by av_read_frame
av_free_packet(packet);
// Handling SDL events there
if SDL_PollEvent(@event) <> 0 then
if (event.type_ = SDL_QUITEV) then
break;
end;
sws_freeContext(img_convert_context);
// Free the YUV frame
av_free(frame);
// Close the codec
avcodec_close(codec_context);
// Close the video file
avformat_close_input(&format_context);
avformat_network_deinit;
// Quit SDL
SDL_QUIT();
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.