首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >libvlc vmem访问冲突

libvlc vmem访问冲突
EN

Stack Overflow用户
提问于 2013-03-20 08:14:42
回答 2查看 1.2K关注 0票数 3

在我的项目中,我使用paslibvlc从h.264中的ip摄像头获取视频。我需要从这个流中获取快照,并尝试对其使用vmem。我的项目是用delphi 7编写的。当我用字符串"rtsp://ip/main“连接到摄像机时,一切正常,但是当我设置回调和格式化时,就会出现访问内存冲突的错误。有人能对我说,我做错了什么吗?这是密码

代码语言:javascript
复制
PBytes = ^TBytes;
TBytes = array of byte;

var
   MainForm: TMainForm;
   ctx:TBytes;

const
   cameraURL = 'rtsp://192.168.123.100/main';

function lock(opaque : Pointer; var planes : Pointer) : Pointer;
function unlock(opaque : Pointer; picture : Pointer; planes : Pointer) : Pointer;
function display(opaque : Pointer; picture : Pointer) : Pointer;

implementation

{$R *.dfm}


function lock(opaque : Pointer; var planes : Pointer) : Pointer;
begin
   planes := x;
end;

function unlock(opaque : Pointer; picture : Pointer; planes : Pointer) : Pointer;
begin
end;

function display(opaque : Pointer; picture : Pointer) : Pointer;
begin
end;

procedure TMainForm.PlayerInit();
var
  args: packed array[0..6] of PAnsiChar;
begin
  libvlc_dynamic_dll_init();

  SetLength(ctx, 1280*720*4+32);

  if (libvlc_dynamic_dll_error <> '') then
  begin
    MessageDlg(libvlc_dynamic_dll_error, mtError, [mbOK], 0);
    exit;
  end;

   args[0] := PAnsiChar(libvlc_dynamic_dll_path);
   args[1] := '--no-video-title-show';
   args[2] := '--no-xlib';
   args[3] := '--no-audio';

  p_li := libvlc_new(Length(args)-1, @args[0]);
  p_mi := NIL;
end;

procedure TMainForm.PlayerPlay(fileName: WideString);
var
  p_md: libvlc_media_t_ptr;
begin
  btm:=Tbitmap.Create;
  btm.Width:=1280;
  btm.Height:=720;
  PlayerStop();

  // create new media from fileName
  p_md := libvlc_media_new_path(p_li, PAnsiChar(System.UTF8Encode(fileName)));

  //libvlc_media_player_set_media(p_mi, p_md);
  p_mi := libvlc_media_player_new_from_media(p_md);

  if (p_mi <> NIL) then
  begin
   libvlc_video_set_callbacks(p_mi,@lock,@unlock,@display,@ctx);
   libvlc_video_set_format(p_mi, 'RV32', 1280, 720, 1280*4);
    //libvlc_media_player_set_hwnd(p_mi, btm.Handle);
  end;

  // play
  libvlc_media_player_play(p_mi);

  // release media
  if (p_md <> NIL) then
  begin
    libvlc_media_release(p_md);
    // p_md := NIL;
  end;
end;



procedure TMainForm.FormActivate(Sender: TObject);
begin
  PlayerInit();
  PlayerPlay(cameraURL);
end;
EN

回答 2

Stack Overflow用户

发布于 2013-03-20 08:28:37

回调使用register调用约定。但这是特尔斐特有的呼叫约定。您的库使用cdecl。这可以从库的Pascal源代码中看到:

代码语言:javascript
复制
type
  libvlc_video_lock_cb    = function(opaque : Pointer; 
      var planes : Pointer) : Pointer; cdecl;
  libvlc_video_unlock_cb  = function(opaque : Pointer; 
      picture : Pointer; planes : Pointer) : Pointer; cdecl;
  libvlc_video_display_cb = function(opaque : Pointer; 
      picture : Pointer) : Pointer; cdecl;

您需要更改回调以匹配库的调用约定。

如果您没有使用@操作符来获取函数指针,编译器就会告诉您这一切。这样做意味着编译器不会检查函数指针的签名是否与声明的签名相匹配。这是人们最常见的错误之一。无论出于什么原因,获得函数指针的方法都是使用@运算符,这种说法一直存在。

总之,需要将cdecl添加到回调函数中:

代码语言:javascript
复制
function lock(opaque : Pointer; var planes : Pointer) : Pointer; cdecl;
function unlock(opaque : Pointer; picture : Pointer; 
    planes : Pointer) : Pointer; cdecl;
function display(opaque : Pointer; picture : Pointer) : Pointer; cdecl;

然后停止使用@获取函数指针:

代码语言:javascript
复制
libvlc_video_set_callbacks(p_mi, lock, unlock, display, @ctx);
票数 3
EN

Stack Overflow用户

发布于 2013-03-29 02:50:41

所有的问题都在于我如何分配内存。在第一个主题中,我在像SetLength(ctx,1280*720*4+32)这样的程序的本地内存中分配内存,但是为了工作顺利,我必须使用AllocMem来使用非托管内存。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15518361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档