[SDL 问题] Delphi SDL 开发遇到问题

cc370052078 2012-07-26 06:59:58

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SDL, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;


var
Form1: TForm1;

implementation
uses
avformat, avcodec, avutil, mem, swscale,FFMPEGDynamiccall;
{$R *.dfm}
function SDL_Auxilipitary_ForDelphi(var pict:PAVPicture;var bmp:PSDL_Overlay):Integer;stdcall;external 'delphiSDL.dll';
function SDL_GetOverlayPix(const bmp:PSDL_Overlay;const i : integer):System.PByte;stdcall;external 'delphiSDL.dll';
function SDL_GetOverlayPit(const bmp:PSDL_Overlay;const i : integer):Integer;stdcall;external 'delphiSDL.dll';
procedure TForm1.FormCreate(Sender: TObject);
begin
// 初始化 SDL
if(SDL_Init(SDL_INIT_VIDEO or SDL_INIT_AUDIO or SDL_INIT_TIMER) < 0) then
showmessage(Format('Couldn''t initialize SDL : %s',[SDL_GetError]));
// 初始化 FFMPEG 库
// 动态调用
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\pthreadGC2.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\xvidcore.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\avutil.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\swscale.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\avcodec.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\avfilter.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\avformat.dll');
FFCall_AddLibrary('D:\Delphi\ffmpeg 研究工程\avcodeclib\avdevice.dll');
FFCall_Init;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
filename = 'E:\Sample.avi'; // 得到 H.264 也可以 保存为图片
var
pFormatCtx: PAVFormatContext;
pCodecCtx: PAVCodecContext;
pCodec: PAVCodec;
pFrame: PAVFrame;
pScaleCtx: PSwsContext;
numBytes: integer;
buffer: PByte;
frameFinished : int ;
pict: TAVPicture;
i, videoStream: integer;
ptk : TAVPacket;
CRect : TRect;
// sdl
screen : PSDL_Surface;
bmp:PSDL_Overlay;
begin
av_register_all();
// Open video file
if av_open_input_file ( pFormatCtx, filename, nil, 0, nil ) <> 0 then
raise exception.Create ( 'WTF?! Couldn''t open file!!!' );
// Retrieve stream information
if av_find_stream_info ( pFormatCtx ) < 0 then
raise exception.Create ( 'WTF?! Couldn''t find stream information!!!' );
dump_format ( pFormatCtx, 0, filename, 0 ); // <<<<<< i dont know how its works
// Get a pointer to the codec context for the video stream
videoStream := -1;
for i := 0 to pFormatCtx.nb_streams - 1 do
begin
if pFormatCtx.streams [i].codec.codec_type = CODEC_TYPE_VIDEO then
begin
videoStream := i;
break;
end;
end;

if videoStream = -1 then
raise exception.Create ( 'WTF?! Didn''t find a video stream!' );

pCodecCtx := pFormatCtx.streams [videoStream].codec;
// Open codec
pCodec := avcodec_find_decoder ( pCodecCtx.codec_id );

if pCodec = nil then
raise exception.Create ( 'WTF?! Codec not found!' );
if avcodec_open(pCodecCtx,pCodec) < 0 then
raise exception.Create ( 'WTF?! Could not open codec!');
// Allocate video frame
pFrame:=avcodec_alloc_frame();
// Determine required buffer size and allocate buffer
numBytes := avpicture_get_size(PIX_FMT_RGB24, pCodecCtx.width,pCodecCtx.height);
{$ifndef __DARWIN__}
screen := SDL_SetVideoMode(pCodecCtx.width, pCodecCtx.height, 0, 0);
{$else}
screen := SDL_SetVideoMode(pCodecCtx.width, pCodecCtx.height, 24, 0);
{$endif}
if not assigned(screen) then showmessage(Format('SDL: could not set video mode : %s',[SDL_GetError]));
bmp := SDL_CreateYUVOverlay(pCodecCtx.width, pCodecCtx.height,
SDL_YV12_OVERLAY, screen);
// pFrameRGB := avcodec_alloc_frame;
// avpicture_alloc ( PAVPicture (pFrameRGB), PIX_FMT_RGB32, pCodecCtx.width, pCodecCtx.height );
pScaleCtx := sws_getContext ( pCodecCtx.width, pCodecCtx.height, pCodecCtx.pix_fmt,
pCodecCtx.width, pCodecCtx.height, PIX_FMT_RGB32, SWS_BICUBIC, nil, nil, nil );
i := 0;
while(av_read_frame(pFormatCtx, @ptk)>=0) do begin
i := i + 1;
if(ptk.stream_index = videoStream) then begin
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, @frameFinished,ptk.data, ptk.size);
// Did we get a video frame?
if frameFinished <> 0 then begin

//*************************************************************
// 问题来了
// SDL_GetOverlayPix 我用 C++ 写的动态链接库
{
pict->data[0] = bmp->pixels[0];
pict->data[1] = bmp->pixels[2];
pict->data[2] = bmp->pixels[1];
pict->linesize[0] = bmp->pitches[0];
pict->linesize[1] = bmp->pitches[2];
pict->linesize[2] = bmp->pitches[1];
return 1;
问题就是 这样 黑屏 无法播放!
如果用 delphi 实现
delphi SDL
TSDL_Overlay = record
format: UInt32; // Overlay format
w, h: Integer; // Width and height of overlay
planes: Integer; // Number of planes in the overlay. Usually either 1 or 3
pitches: PUInt16;
// An array of pitches, one for each plane. Pitch is the length of a row in bytes.
pixels: PPUInt8; // 可以看出来 是 数组指针 不是数值
// An array of pointers to the data of each plane. The overlay should be locked before these pointers are used.
hw_overlay: UInt32;
// This will be set to 1 if the overlay is hardware accelerated.
end;

如何还原为数组呢???
}
//*************************************************************


SDL_LockYUVOverlay(bmp);
{showmessage(inttostr(integer(SDL_GetOverlayPix(bmp,0))));
showmessage(inttostr(integer(SDL_GetOverlayPix(bmp,1))));
showmessage(inttostr(integer(SDL_GetOverlayPix(bmp,2))));}
OutputDebugString(PChar(inttostr(SDL_GetOverlayPit(bmp,1))));
// pict := getpict(bmp)^;
pict.data[0] := SDL_GetOverlayPix(bmp,0);
pict.data[1] := SDL_GetOverlayPix(bmp,2);
pict.data[2] := SDL_GetOverlayPix(bmp,1);
pict.linesize[0] := SDL_GetOverlayPit(bmp,0);
pict.linesize[1] := SDL_GetOverlayPit(bmp,2);
pict.linesize[2] := SDL_GetOverlayPit(bmp,1);
OutputDebugString(PChar(inttostr(pict.linesize[2])));
OutputDebugString(PChar(inttostr(integer(SDL_GetOverlayPix(bmp,1)))));
OutputDebugString(PChar(inttostr(integer(pict.data[2]))));
{img_convert(@pict, PIX_FMT_YUV420P,
PAVPicture(pFrame), pCodecCtx.pix_fmt, pCodecCtx.width, pCodecCtx.height);}

sws_scale(pScaleCtx, @pFrame.data, @pFrame.linesize,
0, pCodecCtx.height, @pict.data, @pict.linesize);
SDL_UnlockYUVOverlay(bmp);
Crect.Left := 0;
Crect.top := 0;
Crect.Right := pCodecCtx.width;
Crect.Bottom := pCodecCtx.height;
SDL_DisplayYUVOverlay(bmp, @CRect);
Sleep(4);
if i > 1000 then break;
end;
end;
end;
{
// Convert the image from its native format to RGB
/*sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);*/
// Save the frame to disk
/*if(++i<=5)
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);*/
SDL_LockYUVOverlay(bmp);
AVPicture pict;


// Convert the image into YUV format that SDL uses
/*img_convert(&pict, PIX_FMT_YUV420P,
(AVPicture *)pFrame, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height);*/
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
0, pCodecCtx->height, pict.data, pict.linesize);
SDL_UnlockYUVOverlay(bmp);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp, &rect);
//Sleep(60);

}
end;

end.
...全文
1694 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
laowang2 2014-08-10
  • 打赏
  • 举报
回复
haitao 2014-08-07
  • 打赏
  • 举报
回复
sdl,还以为是 定制语言 。。。
一路随云 2014-08-07
  • 打赏
  • 举报
回复
引用 4 楼 sololie 的回复:
没玩过sdl,这阵在玩asphyre和hge,权衡了一下,决定选hge
ZenGl比HGE来说更完善和好用
sololie 2014-02-05
  • 打赏
  • 举报
回复
没玩过sdl,这阵在玩asphyre和hge,权衡了一下,决定选hge
cp1982 2014-02-05
  • 打赏
  • 举报
回复
楼主怎么解决的,我现在也是黑屏啊.
cc370052078 2012-07-27
  • 打赏
  • 举报
回复
自己完全解决了 了解一下 SDL SDL_DisplayYUVOverlay(bmp, @rect);
发现 rect 结构跟 windows 下的 不一样 - - . 自己太粗心了 还怪 VC++ 封了函数 到了 delphi 就不行了

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧