一、下载ffmpeg-delphi-pascal-headers
下载地址Headers | FFVCL – Delphi FFmpeg VCL Components(Video Encoder and Video Player)
下载 Releases · BtbN/FFmpeg-Builds · GitHub 下载与上面版本对应的DLL库
二、引用单元
libavformat,libavcodec_codec,libavcodec,FFUtils,libavutil,
libavcodec_packet,libavutil_frame,libavutil_error,libswscale,libavutil_pixfmt,libavutil_imgutils
三、解码
//实现解码一帧
procedure TForm1.Button1Click(Sender: TObject);
var
fmt_ctx: PAVFormatContext;
avdec: PAVCodec;
ret: Integer;
video_stream_index: Integer = -1;
dec_ctx: PAVCodecContext;
packet: PAVPacket;
frame: PAVFrame;
label
the_end;
label
Over_ok;
begin
//打开文件
filename:='E:/FdogXvid.avi';
fmt_ctx:=avformat_alloc_context;
ret := avformat_open_input(@fmt_ctx, PAnsiChar(AnsiString(filename)), nil, nil);
ret := avformat_find_stream_info(fmt_ctx, nil);
ret := av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, @avdec, 0);
video_stream_index:=ret;
dec_ctx := avcodec_alloc_context3(avdec);
avcodec_parameters_to_context(dec_ctx, PPtrIdx(fmt_ctx^.streams, video_stream_index)^.codecpar);
ret := avcodec_open2(dec_ctx, avdec, nil);
//解码一帧
frame := av_frame_alloc();
filt_frame := av_frame_alloc();
packet := av_packet_alloc();
while True do
begin
ret := av_read_frame(fmt_ctx, packet);
if ret < 0 then
Break;
if packet^.stream_index = video_stream_index then
begin
ret := avcodec_send_packet(dec_ctx, packet);
if ret < 0 then
Break;
ret := avcodec_receive_frame(dec_ctx, frame);
if (ret = AVERROR_EAGAIN) or (ret = AVERROR_EOF) then
Break
else if ret < 0 then
begin
goto the_end;
end;
{接收一帧完成,如何要多帧这里直接处理 不要跳转到Over_ok}
goto Over_ok;
end;
end;
Over_ok:
//显示图片 图片信息在frame^.data[0-2]中
the_end:
avcodec_free_context(@dec_ctx);
avformat_close_input(@fmt_ctx);
av_frame_free(@frame);
av_frame_free(@filt_frame);
av_packet_free(@packet);
end;
注意frame^.data中分别是YUV数据,不能直接被Timage使用。还没找到如何转换,现在是把data[0]中的数据放到Tbitmap的rgb中,显示是黑白的。
比如
for i:=0 to frame^.width*frame^.height-1 to
begin
(Bitmap.RawImage.Data+i*3)^:=frame^data[0][i];
(Bitmap.RawImage.Data+i*3+1)^:=frame^data[0][i];
(Bitmap.RawImage.Data+i*3+2)^:=frame^data[0][i];
end;