Нарушение прав доступа vvm в libvlc

Я в своем проекте использую paslibvlc, чтобы получить видео с ip камеры, которая транслируется в h.264. Мне нужно получить снимки из этого потока и попытаться использовать для него vmem. Мой проект написан на Delphi 7. Когда я подключаюсь к камере со строкой "rtsp://ip/main", все в порядке, но когда я устанавливаю обратные вызовы и форматирую их, возникает ошибка нарушения памяти доступа. Может кто-нибудь сказать мне, что я делаю не так? это код

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;

2 ответа

Ваши обратные вызовы используют register Соглашение о вызовах. Но это специальное соглашение о вызовах Delphi. Ваша библиотека использует cdecl, Это можно увидеть из исходного кода Pascal для библиотеки:

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 к вашим функциям обратного вызова:

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;

А затем прекратить использование @ чтобы получить указатели на функции:

libvlc_video_set_callbacks(p_mi, lock, unlock, display, @ctx);

Вся проблема была в том, как я выделяю память. В первой теме я выделяю память в памяти локали моей программы, например SetLength(ctx, 1280*720*4+32), но для хорошей работы я должен использовать AllocMem, чтобы использовать неуправляемую память.

Другие вопросы по тегам