Правильное использование libvlc_media_open_cb - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь использовать функцию libvlc_media_new_callbacks для воспроизведения мультимедиа из памяти с помощью libvlc. Эта функция ожидает указателей на четыре функции обратного вызова: Open, Read, Seek и Close.

Declare Function libvlc_media_new_callbacks Lib "libvlc.dll" (Instance As Ptr, OpenCB As Ptr, ReadCB As Ptr, SeekCB As Ptr, CloseCB As Ptr, Opaque As Ptr) As Ptr

Dim opaque As Ptr = SomeOpaqueValue()
Dim handle As Ptr = libvlc_media_new_callbacks(instance, AddressOf MediaOpen, AddressOf MediaRead, AddressOf MediaSeek, AddressOf MediaClose, opaque)

Все обратные вызовы Read, Seek и Close работают нормально, если я не укажу обратный вызов Open, но это означает, что libvlc не будет знать, какова длина носителя.

Когда я делаю , указываю обратный вызов Open, он вызывается с правильным параметром opaque, но другие обратные вызовы получают вместо этого нулевой указатель. Это делает невозможным узнать, над каким потоком должен работать обратный вызов.

Я неправильно понял цель открытого обратного вызова?

Вот мои функции обратного вызова:

Shared Function MediaOpen(Opaque As Ptr, Buffer As Ptr, ByRef BufferSize As UInt64) As UInt32
  Dim r As BinaryStream = Streams.Lookup(Opaque, Nil)
  If r = Nil Then Return 1 ' invalid Opaque

  Buffer = Nil  ' Not sure what to do with this parameter
  BufferSize = r.Length
  Return 0
End Function
Shared Sub MediaClose(Opaque As Ptr)
  If Streams.HasKey(Opaque) Then Streams.Remove(Opaque)
  If Streams.Count = 0 Then Streams = Nil
End Sub
Shared Function MediaRead(Opaque As Ptr, Buffer As Ptr, BufferSize As Integer) As UInt32
  Dim r As BinaryStream = Streams.Lookup(Opaque, Nil)
  If r = Nil Then Return 0 ' invalid Opaque

  Dim mb As MemoryBlock = Buffer
  Dim data As MemoryBlock = r.Read(BufferSize)
  mb.StringValue(0, data.Size) = data
  Return data.Size
End Function
Shared Function MediaSeek(Opaque As Ptr, Offset As UInt64) As Int32
  Dim r As BinaryStream = Streams.Lookup(Opaque, Nil)
  If r = Nil Then Return 1 ' invalid Opaque
  If Offset > r.Length Then Return 1 ' invalid offset

  r.Position = Offset
  Return 0
End Function

1 Ответ

0 голосов
/ 02 мая 2018

Согласно документации, вы должны выделить буфер и вернуть его адрес в параметре буфера open (для этого вам нужно изменить его на параметр ByRef!). Затем вы получите тот же буферный ptr, переданный в другие функции.

В идеале вы бы установили

Buffer = r

в MediaOpen. Но Xojo не позволит вам. Вместо этого вам нужно сохранить словарь, в котором вы храните r, а затем связать его со значением, которое вы можете присвоить параметру Buffer.

Вот пример (не тестировался):

Static Property OpenedBuffers as Dictionary
Static Property OpenedBufferID as Integer

Shared Function MediaOpen(Opaque As Ptr, ByRef HandleOut As Integer, ByRef BufferSize As UInt64) As UInt32
  Dim r As BinaryStream = Streams.Lookup(Opaque, Nil)
  If r = Nil Then Return 1 ' invalid Opaque
  if OpenedBuffers = nil then OpenedBuffers = new Dictionary
  OpenedBufferID = OpenedBufferID + 1
  OpenedBuffers.Value(OpenedBufferID) = r
  HandleOut = OpenedBufferID
  BufferSize = r.Length
  Return 0
End Function

Shared Function MediaRead(Handle As Integer, Buffer As Ptr, BufferSize As Integer) As UInt32
  Dim r As BinaryStream = OpenedBuffers.Value(Handle)
  ...

Shared Sub MediaClose(Handle As Integer)
  Dim r As BinaryStream = OpenedBuffers.Value(Handle)
  OpenedBuffers.Remove (Handle)
  If Streams.HasKey(r) Then Streams.Remove(r)
  ...

Надеюсь, это поможет

...