Failure: calling pjlib from unknown/external thread

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi everybody,

I know that the topic was discussed long time ago
(and many times) but I didn't still find a solution
to this issue for my project.

I wrote a little Windows standard DLL
(compiled with VC6 using pjsip ver 0.8.0)
to stream RTP audio over UDP sockets.
I use this dll in visual basic 6 projects.
The problem is that when I start streaming,
calling the sub "StartStream" mapped in the DLL,
I get:
     "Calling pjlib from unknown/external thread. You must "
     "register external threads with pj_thread_register() "
     "before calling any pjlib functions."


I read I must register the thread but I don't
know which thread (..sorry i'm bad with threads,
vb6 don't want the developer familiar with them!)
and where register it.
That's the source code of the DLL,
any contribute will be really appreciated.

Andrea




#include <pjlib.h>
#include <pjlib-util.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>

#include <stdlib.h> /* atoi(): Convert string to integer */
#include <stdio.h>

#include "util.h"

#define THIS_FILE "pjdll.cpp"


#include <string>
#include <atlbase.h>



BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
    return TRUE;
}




/*
 * Register codecs.
 */
static pj_status_t init_codecs(pjmedia_endpt *med_endpt)
{
    pj_status_t status;

    /* To suppress warning about unused var when all codecs are disabled */
    PJ_UNUSED_ARG(status);

#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
    status = pjmedia_codec_g711_init(med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC!=0
    status = pjmedia_codec_gsm_init(med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
    status = pjmedia_codec_speex_init(med_endpt, 0, -1, -1);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC!=0
    status = pjmedia_codec_l16_init(med_endpt, 0);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

    return PJ_SUCCESS;
}







/*
 * Unregister all codecs.
 */
static pj_status_t deinit_codecs()
{
    pj_status_t status;

    /* To suppress warning about unused var when all codecs are disabled */
    PJ_UNUSED_ARG(status);

#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
    status = pjmedia_codec_g711_deinit();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC!=0
    status = pjmedia_codec_gsm_deinit();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
    status = pjmedia_codec_speex_deinit();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC!=0
    status = pjmedia_codec_l16_deinit();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#endif

    return PJ_SUCCESS;
}






/*
 * Create stream based on the codec, dir, remote address, etc.
 */
static pj_status_t create_stream( pj_pool_t *pool,
      pjmedia_endpt *med_endpt,
      const pjmedia_codec_info *codec_info,
      pjmedia_dir dir,
      pj_uint16_t local_port,
      const pj_sockaddr_in *rem_addr,
      pjmedia_stream **p_stream )
{
    pjmedia_stream_info info;
    pjmedia_transport *transport = NULL;
    pj_status_t status;


    /* Reset stream info. */
    pj_bzero(&info, sizeof(info));
 status = pj_init();


    /* Initialize stream info formats */
    info.type = PJMEDIA_TYPE_AUDIO;
    info.dir = dir;
    pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info));
    info.tx_pt = codec_info->pt;
    info.ssrc = pj_rand();


    /* Copy remote address */
    pj_memcpy(&info.rem_addr, rem_addr, sizeof(pj_sockaddr_in));


    /* Create media transport */
    status = pjmedia_transport_udp_create(med_endpt, NULL, local_port,
       0, &transport);
    if (status != PJ_SUCCESS)
 return status;


    /* Now that the stream info is initialized, we can create the
     * stream.
     */

    status = pjmedia_stream_create( med_endpt, pool, &info,
        transport, NULL, p_stream);

    if (status != PJ_SUCCESS) {
  app_perror(THIS_FILE, "Error creating stream", status);
  pjmedia_transport_udp_close(transport);
  return status;
    }


    return PJ_SUCCESS;
}





/*
 * main()
 */

pj_caching_pool cp;
pjmedia_endpt *med_endpt;
pj_pool_t *pool;
pjmedia_snd_port *snd_port = NULL;
pjmedia_stream *stream = NULL;
pjmedia_port *stream_port = NULL;
pj_status_t status;



extern "C" __declspec(dllexport) int __stdcall StartStream(long LocalPort, 
LPSTR strRemoteIP, long RemotePort)
{
    /* Default values */
    const pjmedia_codec_info *codec_info = NULL;
    pjmedia_dir dir = PJMEDIA_DIR_DECODING;
    pj_sockaddr_in remote_addr;
    pj_uint16_t local_port = 4000;
    char *codec_id = NULL;


    pj_bzero(&remote_addr, sizeof(remote_addr));


    /* init PJLIB : */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);


    /* Parse arguments */
 local_port = (pj_uint16_t) LocalPort;
    if (local_port < 1) {
  printf("Error: invalid local port %s\n", pj_optarg);
  return 1;
    }


 //USES_CONVERSION;
 //std::string ipstr = std::string(W2A((wchar_t *) strRemoteIP));
    //LPSTR ipstr = W2A((wchar_t *) strRemoteIP);
 //const char ttt[] ="127.0.0.1";
 //ipstr = "127.0.0.1";
 //char *ttt = W2A((wchar_t *) strRemoteIP);


 pj_str_t ip = pj_str(strRemoteIP);
 pj_uint16_t port = (pj_uint16_t) RemotePort;

 status = pj_sockaddr_in_init(&remote_addr, &ip, port);
 if (status != PJ_SUCCESS) {
      app_perror(THIS_FILE, "Invalid remote address", status);
      return 2;
 }
 dir = PJMEDIA_DIR_ENCODING_DECODING;



    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);

    /*
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    /* Create memory pool for application purpose */
    pool = pj_pool_create( &cp.factory,     /* pool factory     */
      "app",     /* pool name.     */
      4000,     /* init size     */
      4000,     /* increment size     */
      NULL      /* callback on error    */
      );


    /* Register all supported codecs */
    status = init_codecs(med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);


    /* Find which codec to use. */
    //codec_id = pj_optarg;
    if (codec_id) {
  unsigned count = 1;
  pj_str_t str_codec_id = pj_str(codec_id);
  pjmedia_codec_mgr *codec_mgr = pjmedia_endpt_get_codec_mgr(med_endpt);
  status = pjmedia_codec_mgr_find_codecs_by_id( codec_mgr,
            &str_codec_id, &count,
            &codec_info, NULL);
  if (status != PJ_SUCCESS) {
   printf("Error: unable to find codec %s\n", codec_id);
   return 4;
  }
    } else {
 /* Default to pcmu */
  pjmedia_codec_mgr_get_codec_info( pjmedia_endpt_get_codec_mgr(med_endpt),
       0, &codec_info);
  if (status != PJ_SUCCESS) {
   printf("Error: unable to find/use default codec");
   return 41;
  }
    }

    /* Create stream based on program arguments */
    status = create_stream(pool, med_endpt, codec_info, dir, local_port,
      &remote_addr, &stream);
    if (status != PJ_SUCCESS) {
     //goto on_exit;
     return 5;
 }


    /* Get the port interface of the stream */
    status = pjmedia_stream_get_port( stream, &stream_port);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);



 /* Create sound device port. */
  status = pjmedia_snd_port_create(pool, -1, -1,
     stream_port->info.clock_rate,
     stream_port->info.channel_count,
     stream_port->info.samples_per_frame,
     stream_port->info.bits_per_sample,
     0, &snd_port);


 if (status != PJ_SUCCESS) {
     app_perror(THIS_FILE, "Unable to create sound port", status);
     //goto on_exit;
  return 6;
 }

 /* Connect sound port to stream */
 status = pjmedia_snd_port_connect( snd_port, stream_port );
 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    /* Start streaming */
    pjmedia_stream_start(stream);


    /* Done */
 printf("Stream is active, send/recv, local port is %d, "
        "sending to %s:%d\n",
        local_port,
        pj_inet_ntoa(remote_addr.sin_addr),
        pj_ntohs(remote_addr.sin_port));


return 0;

    /* Start deinitialization: */
    return (status == PJ_SUCCESS) ? 0 : 1;
}



extern "C" __declspec(dllexport) int __stdcall StopStream()
{
     /* Destroy sound device */
    if (snd_port) {
  pjmedia_snd_port_destroy( snd_port );
  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
    }

    /* Destroy stream */
    if (stream) {
  pjmedia_transport *tp;

  tp = pjmedia_stream_get_transport(stream);
  pjmedia_stream_destroy(stream);
  pjmedia_transport_udp_close(tp);
    }

 deinit_codecs();

    /* Release application pool */
    pj_pool_release( pool );

    /* Destroy media endpoint. */
    pjmedia_endpt_destroy( med_endpt );

    /* Destroy pool factory */
    pj_caching_pool_destroy( &cp );

    /* Shutdown PJLIB */
    pj_shutdown();


pj_caching_pool *cp = NULL;
pjmedia_endpt *med_endpt = NULL;
pj_pool_t *pool = NULL;
pjmedia_snd_port *snd_port = NULL;
pjmedia_stream *stream = NULL;
pjmedia_port *stream_port = NULL;


    return (status == PJ_SUCCESS) ? 0 : 1;
} 




[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux