maybe you can put register thread function inside every functions of your dll. regards, Gang On Wed, Sep 24, 2008 at 7:12 PM, programmer <programmer at supereva.it> wrote: > 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; > } > > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip at lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20080925/59f930e7/attachment.html>