[UOS] 飞腾2000+UOS+lazarus+ffmpeg解码效率奇低
Tofloor
default avatar
vster
deepin
2024-02-23 04:31
Author

运行环境如题,详细如图。简单的调用ffmpeg 动态库解码1080P h264文件,结果解码每帧要40-70毫秒,正常应该是10毫秒左右。

同样的机器,同样的ffmpeg库和调用逻辑,换做qt creator就效率正常。求助各位,看有哪些因素导致。谢谢。

后附主要代码。解码函数avcodec_decode_video2耗时40-70毫秒。
图片.png

Program ffmpeg_sample_player;

Uses
//Windows,
SysUtils,
Classes,

libSDL2,

ffmpeg_loader,

ffmpeg_types,
libavcodec,
libavdevice,
libavfilter,
libavformat,
libavutil,
libpostproc,
libswresample,
libswscale;

Var
err: Integer;
filename: AnsiString;
pFormatCtx: pAVFormatContext = Nil;
pCodecCtx: pAVCodecContext;
pCodec: pAVCodec;
screen: pSDL_Surface;
//bmp: pSDL_Overlay;
sdlWindow: PSDL_Window;
sdlRenderer: PSDL_Renderer;
sdlTexture: PSDL_Texture;
img_convert_context: pSwsContext;
frame: pAVFrame;
pFrameYUV420P: pAVFrame;
packet: AVPacket;
frame_finished: Integer;
pict: AVPicture;
rect: TSDL_Rect;
event: TSDL_Event;
FLoaderFFmpeg: TLoaderFFmpeg;
i,videoStream:Integer;
xoptions: pAVDictionary = nil;
curDir: string;
h264File: THandle;
itick: cardinal;

Procedure ExitX;
begin
WriteLN(' ');
WriteLN('-----ERROR-------------');
WriteLN('Press any key to Exit...');
ReadLN;
Halt(0);
end;

function alloc_avframe(pix_fmt: AVPixelFormat; width, height: integer): PAVFrame;
var
picture: PAVFrame;
picture_buf: PByte;
size: integer;
begin
Result := nil;

picture := av_frame_alloc();
if (picture = nil) then
Exit;

size := av_image_get_buffer_size(pix_fmt, width, height, 1);
picture_buf := av_malloc(size);
if (picture_buf = nil) then
begin
av_frame_free(picture);
Exit;
end;
av_image_fill_arrays(@picture^.data[0], @picture^.linesize[0], picture_buf, pix_fmt, width, height, 1);
Result := picture;
end;

Begin

curDir := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0)));
filename := curDir + 'video.h264';
{$if defined(windows)}
curDir := curDir + 'windows_sdl2' + DirectorySeparator;
{$else}
curDir := curDir + 'linux_sdl' + DirectorySeparator;
{$ifend}

libSDL2_Load(curDir + SDL_LibName);
If libSDL2_IsLoaded = False Then
Begin
WriteLn('Unable to Load SDL2 Library');
ExitX;
End;

FLoaderFFmpeg := TLoaderFFmpeg.Create(Nil);
FLoaderFFmpeg.Active := true;
If (FLoaderFFmpeg.IslibavCodec_Loaded = False) Or
(FLoaderFFmpeg.IslibavDevice_Loaded = False) Then
Begin
WriteLn('Unable to Load libavCodec Library');
ExitX;
End;

Try

av_register_all(); avformat_network_init(); pFormatCtx:=avformat_alloc_context(); // Open video file pFormatCtx := avformat_alloc_context(); err := avformat_open_input(pFormatCtx, PAnsiChar(filename), Nil, xoptions); If (err < 0) Then Begin WriteLn('ffmpeg: Unable to open input file'); ExitX; End; // Retrieve stream information err := avformat_find_stream_info(pFormatCtx, xoptions); If (err < 0) Then Begin WriteLn('ffmpeg: Unable to find stream info'); ExitX; End; // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, PAnsiChar(filename), 0); // Find the first video stream videoStream:=-1; For i := 0 To pFormatCtx^.nb_streams - 1 Do If (pFormatCtx^.streams^[i].codec^.codec_type = AVMEDIA_TYPE_VIDEO) Then begin videoStream:=i; break; end; If (videoStream <0) Then Begin WriteLn('ffmpeg: Unable to find video stream'); ExitX; End; // Get a pointer to the codec context for the video stream pCodecCtx := pFormatCtx^.streams^[videoStream].codec; // Find the decoder for the video stream pCodec := Nil; pCodec := avcodec_find_decoder(pCodecCtx^.codec_id); if pCodec=nil then begin WriteLn('Unsupported codec!'); ExitX; end; // Open codec err := avcodec_open2(pCodecCtx, pCodec, Nil); If (err < 0) Then Begin WriteLn('ffmpeg: Unable to open codec'); ExitX; End; sdlWindow := SDL_CreateWindow('demo', 0, 0, pCodecCtx^.width, pCodecCtx^.height, SDL_WINDOW_OPENGL); sdlRenderer := SDL_CreateRenderer(sdlWindow, -1, 0); sdlTexture := SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx^.width, pCodecCtx^.height); img_convert_context := sws_getCachedContext( Nil, pCodecCtx^.width, pCodecCtx^.height, AVPixelFormat(pCodecCtx^.pix_fmt), pCodecCtx^.width, pCodecCtx^.height, AVPixelFormat(AV_PIX_FMT_YUV420P), SWS_BICUBIC, Nil, Nil, Nil); If (img_convert_context = Nil) Then Begin WriteLn('Cannot initialize the conversion context'); ExitX; End; frame := av_frame_alloc(); pFrameYUV420P := alloc_avframe(AV_PIX_FMT_YUV420P, pCodecCtx^.width, pcodecctx^.height); While (av_read_frame(pFormatCtx, packet) >= 0) Do Begin If (packet.stream_index = videoStream) Then 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, @pFrameYUV420P^.data[0], @pFrameYUV420P^.linesize[0]); SDL_UpdateTexture(sdlTexture, nil, pFrameYUV420P^.data[0], pFrameYUV420P^.linesize[0]); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, nil, nil); SDL_RenderPresent(sdlRenderer); End; End; av_packet_unref(packet); End; sws_freeContext(img_convert_context); av_free(frame); avcodec_close(pCodecCtx); avformat_close_input(pFormatCtx); avformat_network_deinit; SDL_QUIT();

Except
On E: Exception Do
WriteLn(E.ClassName, ': ', E.Message);
End;

FLoaderFFmpeg.free;

WriteLN(' ');
WriteLN('Press any key to Exit...');
ReadLN;
End.

Reply Favorite View the author
All Replies
流浪的加菲
deepin
2024-02-23 08:58
#1

不知道为什么有差异,但是既然已经用UOS系统了,本身也是推荐大家在UOS上使用Qt Creator,而且看你说的使用Qt 解码效率是正常的,那就用Qt来干活咯😂

Reply View the author
deepinzjsxwc
deepin
2025-01-07 02:45
#2

试试把你代码sdl的渲染器用GPU硬件加速渲染,

源代码里这句

sdlRenderer := SDL_CreateRenderer(sdlWindow, -1, 0);

改成

sdlRenderer := SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED);

Reply View the author
New Thread

Popular Events

More
国际排名
WHLUG