From OpalVoipWiki

Main: OpenH323Conversion

Conversion from OpenH323 to OPAL can either be reasonably simple, or very difficult depending on how much your application has overridden the default behaviour in OpenH323. There have been some substantial changes (we believe for the better) in OPAL especifally in the area of media handling.

In OpenH323, you would typically create a derived class from H323EndPoint to override various “callback” virtual functions, which is how the stack communicates actions with the application. Most of these functions have been moved to OpalManager so they can appy to multiple protocols and not just H.323, so now you do essentially the same thing as before, but instead of deriving from H323EndPoint you derive from OpalManager. Care will need to be taken when doing so as some have changed signature (e.g. a H323Connection parameter changed to OpalConnection), some have moved to other classes and some have disappeared entirely as the architecture no longer requires them.

As we are all programmers here, the best method of describing the issues is a worked example of converting the example in openh323/samples/simple to OPAL.

Here is the original PProcess class for the simple example:

class SimpleH323Process : public PProcess
{
  PCLASSINFO(SimpleH323Process, PProcess)

  public:
    SimpleH323Process();
    ~SimpleH323Process();

    void Main();

  protected:
    SimpleH323EndPoint * endpoint;
};

which is very simple to change. SimpleH323EndPoint becomes SimpleManager and that's all

class SimpleH323Process : public PProcess
{
.....
  protected:
    SimpleManager * manager;
};

Next is the main class:

class SimpleH323EndPoint : public H323EndPoint
{
  PCLASSINFO(SimpleH323EndPoint, H323EndPoint);

  public:
    SimpleH323EndPoint();
    ~SimpleH323EndPoint();

    // overrides from H323EndPoint
    virtual H323Connection * CreateConnection(unsigned callReference);
    virtual BOOL OnIncomingCall(H323Connection &, const H323SignalPDU &, H323SignalPDU &);
    virtual H323Connection::AnswerCallResponse OnAnswerCall(
      H323Connection &,
      const PString &,
      const H323SignalPDU &,
      H323SignalPDU &
    );
    virtual BOOL OnConnectionForwarded(H323Connection &, const PString &, const H323SignalPDU &);
    virtual void OnConnectionEstablished(H323Connection & connection, const PString & token);
    virtual void OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken);
    virtual BOOL OpenAudioChannel(H323Connection &, BOOL, unsigned, H323AudioCodec &);

    // New functions
    BOOL Initialise(PArgList &);
    BOOL SetSoundDevice(PArgList &, const char *, PSoundChannel::Directions);

    PString currentCallToken;

  protected:
    BOOL autoAnswer;
    PString busyForwardParty;
};

Many of these call back functions now belong in the manager, so it is in effect split into two classes, the first is the existing H323EndPoint derived class:

class SimpleH323EndPoint : public H323EndPoint
{
  PCLASSINFO(SimpleH323EndPoint, H323EndPoint);

  public:
    SimpleH323EndPoint();
    ~SimpleH323EndPoint();

    // overrides from H323EndPoint
    virtual H323Connection * CreateConnection(
      OpalCall & call,                         ///<  Call object to attach the connection to
      const PString & token,                   ///<  Call token for new connection
      void * userData,                         ///<  Arbitrary user data from MakeConnection
      OpalTransport & transport,               ///<  Transport for connection
      const PString & alias,                   ///<  Alias for outgoing call
      const H323TransportAddress & address,    ///<  Address for outgoing call
      H323SignalPDU * setupPDU,                ///<  Setup PDU for incoming call
      unsigned options = 0,
      OpalConnection::StringOptions * stringOptions = NULL ///<  complex string options
    );
};

This class only exists so it can override the CreateConnection function so a custom H323Connection derived class can be created. That virtual function acquired many more parameters during it's conversion to OPAL!

We have a quick aside here to deal with the last remaining class in the simple sample before we move on to the new manager class.

class SimpleH323Connection : public H323Connection
{
    PCLASSINFO(SimpleH323Connection, H323Connection);

  public:
    SimpleH323Connection(SimpleH323EndPoint &, unsigned);

    virtual BOOL OnStartLogicalChannel(H323Channel &);
    virtual void OnUserInputString(const PString &);

  protected:
    BOOL noFastStart;
};

which becomes:

class SimpleH323Connection : public H323Connection
{
    PCLASSINFO(SimpleH323Connection, H323Connection);

  public:
    SimpleH323Connection(
      OpalCall & call,                         ///<  Call object connection belongs to
      H323EndPoint & endpoint,                 ///<  H323 End Point object
      const PString & token,                   ///<  Token for new connection
      const PString & alias,                   ///<  Alias for outgoing call
      const H323TransportAddress & address,    ///<  Address for outgoing call
      unsigned options = 0,                    ///<  Connection option bits
      OpalConnection::StringOptions * stringOptions = NULL ///<  complex string options
    );

    virtual BOOL OnStartLogicalChannel(H323Channel &);

  protected:
    BOOL noFastStart;
};

Note the OnUserInputString has been removed, as this is now also at the OpalManager level. The other change is all the additional parameters that we added to CreateConnection.

So, now we come to the core of the conversion process, the manager class:

class SimpleManager : public OpalManager
{
    PCLASSINFO(SimpleManager, OpalManager);

  public:
    SimpleManager();
    ~SimpleManager();

    virtual PBoolean OnForwarded(OpalConnection & connection, const PString & remoteParty);
    virtual void OnEstablishedCall(OpalCall & call);
    virtual void OnClearedCall(OpalCall & call);

    // New functions
    BOOL Initialise(PArgList &);

    PString currentCallToken;

  protected:
    PString busyForwardParty;
};

So we have some function translations:

    virtual BOOL OnConnectionForwarded(H323Connection &, const PString &, const H323SignalPDU &);
    virtual void OnConnectionEstablished(H323Connection & connection, const PString & token);
    virtual void OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken);

became

    virtual PBoolean OnForwarded(OpalConnection & connection, const PString & remoteParty);
    virtual void OnEstablishedCall(OpalCall & call);
    virtual void OnClearedCall(OpalCall & call);

but they all server exactly the same purpose as before, they are just abtracted for any protocol and not specific to the H.323 class names.

The astute student may have noticed that there are some call back functions not translated yet. These are related to the local PC functions such was what sound card is used etc. In OpenH323 these were just functions on the derived H323EndPoint, however in OPAL they are an entirely new class:

class SimplePCSSEndPoint : public OpalPCSSEndPoint
{
  PCLASSINFO(SimplePCSSEndPoint, OpalPCSSEndPoint);

  public:
    SimplePCSSEndPoint(SimpleManager & manager);

    virtual PBoolean OnShowIncoming(const OpalPCSSConnection & connection);
    virtual PBoolean OnShowOutgoing(const OpalPCSSConnection & connection);

    PBoolean SetSoundDevice(PArgList & args, const char * optionName, PSoundChannel::Directions dir);

    PString incomingConnectionToken;
    bool    autoAnswer;
};

So, here we have the H323EndPoint function:

    virtual BOOL OnIncomingCall(H323Connection &, const H323SignalPDU &, H323SignalPDU &);

which has changed to:

    virtual PBoolean OnShowIncoming(const OpalPCSSConnection & connection);

and the function:

    virtual BOOL OpenAudioChannel(H323Connection &, BOOL, unsigned, H323AudioCodec &);

has effectively vanished. This is because the OpalPCSSEndPoint and OpalPCSSConnection classes now handle that functionality. It is likely that if an application is overriding this function to change the default sound card media handling, they should consider the OpalLocalEndPoint class instead of OpalPCSSEndPoint which is specifically designed for application specific media handling.

The last remaining function:

    virtual H323Connection::AnswerCallResponse OnAnswerCall(
      H323Connection &,
      const PString &,
      const H323SignalPDU &,
      H323SignalPDU &
    );

still exists on H323EndPoint and also OpalManager, and could be still used, though the new OPAL architecture only requires it where early media is involved. For most applications it is no longer required.

That's all for now, eventually we will get around to giving the implementations for the new classes above, but this document should at least get you started on the road to OPAL. You may decide it is easier to just start from scratch or never change from the OpenH323 API, that is a tricky decision, but we believe OPAL is a significant advance on OpenH323, and not just becuase it supports SIP! There is an enormouse amount of built in functionality in OPAL from IVR handling to conferencing to accurate media negotiation. We hope you can make the change!

Retrieved from http://wiki.opalvoip.org/index.php?n=Main.OpenH323Conversion
Page last modified on August 26, 2009, at 01:40 AM