There is bug when use multi RTP session of ccRTP!

Seven Pham <[email protected]>
Newsgroups gmane.comp.gnu.ccrtp.devel
Message-ID <[email protected]>
Hi all,
I use the ccRTP to transfer the audio and video stream. I am stick in 
a bug.  i have spent a lot of time to fix it. But I still can not pass
it. This is my problem:

My application have 2 stream: audio stream and video stream.I use 2
thread for  them. One for send/receiv audio, one for send/receive
video. They can send/receive both audio and video stream. But They
were killed(or application was segmentation fault) after about 5
minutes for streaming. if i stop one stream audio or video and use
only one stream, it can send/receive well.This is the way that i use
multi session of ccRTP:

+ For Audio stream:

class AudioRtpRTX : public Thread, public TimerPort {
public:
        AudioRtpRTX (SipCall *, AudioDrivers *, Manager *, bool, int);
        ~AudioRtpRTX();
        virtual void run ();

private:
        SipCall         *ca;
        AudioDrivers    *audioDevice;
        RTPSession      *sessionSend;
        RTPSession      *sessionRecv;
        SymmetricRTPSession     *session;
        Manager         *manager;
        bool            sym;
        int             line;
};

sessionSend and sessionRecv were created as the following source code:
               InetHostAddress local_ip("0.0.0.0");
                sessionRecv = new RTPSession (local_ip,
getLocalAudioPort(ca));//local audio port is 7070
                sessionSend = new RTPSession (local_ip);

And this is the run()  function of the thread:
void AudioRtpRTX::run(void)
{
        int gran = 160;
        int prev_ts= 0;
        AudioCodec *ac=NULL;
        unsigned char *data_to_send;
        short *data_mute;
        short *data_from_mic;
        int i, compSize, timestamp;
        int expandedSize;
        short *data_for_speakers = NULL;
        int numFrames = 0;
        data_for_speakers = (short *)malloc(2048 *sizeof(short));
        data_from_mic = (short *)malloc(1024 *sizeof( short));
        data_to_send = (unsigned char *)malloc(1024 * sizeof( unsigned char));
        data_mute = (short *)malloc(1024 * sizeof( short));

        InetHostAddress remote_ip(ca->remote_sdp_audio_ip);
        printf("Enter thread AudioRtpRTX:)-Mode %d\n", sym);
     
       //Init the Audio codec, use g711 audio codec
        ac = AudioCodec_new();

        if (!remote_ip) {
           printf("RTX: IP address is not correct!\n");
           this->exit();
        } else {
                printf("RTX: Connected to %s:%d",
                ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port);
        }
       sym = 0;

        // Initialization
        if (!sym) {
                sessionRecv->setSchedulingTimeout (10000);
                sessionRecv->setExpireTimeout(1000000);

                sessionSend->setSchedulingTimeout(10000);
                sessionSend->setExpireTimeout(1000000);
        } 

        if (!sym) {

                //remote_sdp_audio_port is 7070
                if (!sessionSend->addDestination (remote_ip,
                                        (unsigned short)
ca->remote_sdp_audio_port)) {
                        printf("RTX send: could not connect to port %d",
                                        ca->remote_sdp_audio_port);

                        this->exit();
                } else {
                        printf("RTP(Send): Added destination %s:%d",
                                        remote_ip.getHostname(),
                                        (unsigned short)
ca->remote_sdp_audio_port);
                         }

                sessionRecv->setPayloadFormat(StaticPayloadFormat(sptPCMU));
                sessionSend->setPayloadFormat(StaticPayloadFormat(sptPCMU));
                setCancel(cancelImmediate);
                sessionSend->setMark(TRUE);
                sessionSend->setSessionBandwidth(4000000);

           }

        timestamp = 0;
#ifdef SET_TIMER
        // TODO: get frameSize from user config
        int frameSize = 20; // 20ms frames
        TimerPort::setTimer(frameSize);
#endif

        // start running the packet queue scheduler.
        if (!sym) {
                sessionRecv->startRunning();
                sessionSend->startRunning();
                cout << "The RTP queueRV is ";
                if( sessionRecv->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;

                cout << "The RTP queueSend is ";
                if( sessionSend->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;


        }

        while (ca->enable_audio != -1)
        {
                ////////////////////////////
                // Send session
                ////////////////////////////
                if (!manager->mute)
                {
                        i = AudioDrivers_readBuffer_with_data
(audioDevice, data_from_mic, 320);
                }
          
                // Encode acquired audio sample
                compSize = codecEncode (
                                0,
                                data_to_send,
                                data_from_mic, i);

               // Send encoded audio sample
                if (!sym)
                {
                        sessionSend->putData(timestamp, data_to_send,compSize);
                 }
                 timestamp += compSize;

                 //Recv session
                ////////////////////////////
                {

                        const AppDataUnit* adu = NULL;
                        int loop = 0;

                        Thread::sleep(5); // in msec.
                        if (!sym)
                        {
                                adu =
sessionRecv->getData(sessionRecv->getFirstTimestamp());
                        if(adu)
                        {
                               //decode the encode data 
                               expandedSize = codecDecode (
                                        0,
                                        data_for_speakers,
                                        (unsigned
char*)adu->getData(),adu->getSize());

                                // Write decoded data to sound device
                               
AudioBuffer_resize(&manager->audiodriver[line]->audio_buf,
expandedSize);
                                AudioBuffer_setData
(&manager->audiodriver[line]->audio_buf, data_for_speakers);
                                i = AudioDrivers_writeBuffer_with_data
(audioDevice, data_for_speakers, expandedSize);

                                delete adu;
                        }
                }

                // Let's wait for the next transmit cycle
#ifdef SET_TIMER
                Thread::sleep(TimerPort::getTimer());
                TimerPort::incTimer(frameSize); // 'frameSize' ms
#endif

        }
        free(data_for_speakers);
        free(data_from_mic);
        free( data_mute);
        free( data_to_send);
        this->exit();
}

If i define SET_TIMER, the quality of the audio will be very bad

+ For video stream:
The RTP session send/receive for the video stream is like the RTP
session of the audio stream:

 class VideoRtpRTX : public Thread, public TimerPort {
public:
        VideoRtpRTX (SipCall *, VideoDrivers *, Manager *, bool, int);
        ~VideoRtpRTX();
        virtual void run ();

private:
        SipCall         *ca;
        VideoDrivers    *videoDevice;
        RTPSession      *sessionSend;
        RTPSession      *sessionRecv;
        SymmetricRTPSession     *session;
        Manager         *manager;
        bool            sym;
        int             line;
};

sessionSend and sessionRecv were created as the following source code:
               InetHostAddress local_ip("0.0.0.0");
                sessionRecv = new RTPSession (local_ip,
getLocalVideoPort(ca));//local video port is 7072
                sessionSend = new RTPSession (local_ip);
And this is the run function of the thread:

void VideoRtpRTX::run(void)
{
        #define PIC_WIDTH 176
        ##define PIC_HEIGHT 144
        #define FRAME_SIZE  (PIC_WIDTH*PIC_HEIGHT*3/2) //frame size of
the YUV picture


        unsigned char *data_to_send;
        unsigned char *data_compressed;
        unsigned char *data_from_wc;
        unsigned char *data_for_lcd = NULL;
        // TODO: get frameSize from user config
        int frameSize = 100; // 100ms frames
        unsigned long numFrames = 0;
        InetHostAddress remote_ip(ca->remote_sdp_audio_ip);

        data_for_lcd = (unsigned char *)malloc(FRAME_SIZE);
        data_from_wc = (unsigned char *)malloc(FRAME_SIZE);
        data_to_send = (unsigned char *)malloc(FRAME_SIZE);
        data_compressed = (unsigned char *)malloc(FRAME_SIZE);
        printf("Enter thread VideoRtpRTX\n");

       sym = 0;
        // Initialization
        if (!sym) {
                sessionRecv->setSchedulingTimeout(120000);
                sessionRecv->setExpireTimeout(12000000);

                sessionSend->setSchedulingTimeout(120000);
                sessionSend->setExpireTimeout(12000000);
        }

        if (!sym) {

                if (!sessionSend->addDestination (remote_ip,
                                        (unsigned
short)ca->remote_sdp_video_port)) {
                        //remote_sdp_video_port is 7072
                        printf("RTX send: could not connect to port %d",
                                ca->remote_sdp_video_port);
                        free(data_for_lcd);
                        free(data_from_wc);
                        free( data_compressed);
                        free( data_to_send);
                        this->exit();


                } else {
                        printf("RTP(Send): Added destination %s:%d\n",
                                        remote_ip.getHostname(),
                                        (unsigned
short)ca->remote_sdp_video_port);
                }

                sessionRecv->setPayloadFormat(DynamicPayloadFormat(
                ca->video_payload, 90000));
                sessionSend->setPayloadFormat(DynamicPayloadFormat(
                ca->video_payload, 90000));
                 //video_payload is 96
                
                setCancel(cancelImmediate);
                sessionSend->setMark(true);
                sessionSend->setSessionBandwidth(4000000);


        }

       TimerPort::setTimer(frameSize);//100ms
        // start running the packet queue scheduler.
        if (!sym) {
                sessionRecv->startRunning();
                sessionSend->startRunning();

                cout << "The RTP queueRV is ";
                if( sessionRecv->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;

                cout << "The RTP queueSend is ";
                if( sessionSend->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;
        }

        int packetsPerSecond = 10;
        uint16 tstampInc = sessionSend->getCurrentRTPClockRate() /
packetsPerSecond;
        while(ca->enable_video != -1)
        {

                ////////////////////////////
                // Send session
                ////////////////////////////
                //Read one frame YUV from a file into the data_from_wc buffer
                int i = readVideoFrame(data_from_wc, FRAME_SIZE);
                if( i>0 )
                {
                //right now, i use the XVID codec bitrate 40000, 10fps
                #ifdef ADD_CODEC
                        int complen;
                        int keyframe = -1;
                        complen = VideoEncImage(data_from_wc, i,
data_to_send, keyframe);
                        if(complen<0)
                        {
                                printf("encode fail");
                                continue;
                        }
                #endif
                        // send an RTP packet
                        if(!sym)
                        {
                                Thread::sleep(2);
                #ifdef ADD_CODEC
                               
sessionSend->putData(numFrames*tstampInc, data_to_send, complen);
                                numFrames++;
                #else
                               
sessionSend->putData(numFrames*tstampInc, data_from_wc,FRAME_SIZE);
                                numFrames++;
                #endif
                 }else{ //end of file, close and reopen the file
                        closeVideoInput();
                        openVideoInput(VIDEOFILE);

                }

                 ////////////////////////////
                // Recv session
                ////////////////////////////
                const AppDataUnit* adu = NULL;
                Thread::sleep(5); // in msec.
                 if (!sym) {
                      adu =
sessionRecv->getData(sessionRecv->getFirstTimestamp());

                 }

                if (adu)
                {
                        int decomplen;
        #ifdef ADD_CODEC
                        //decode the frame and write it to frame buffer
                        decomplen = VideoDecImage((unsigned
char*)adu->getData(), data_for_lcd, adu->getSize());
                        usleep(2);
                        if(decomplen<0){
                                printf("decode video image fail\n");
                                delete adu;
                                continue;
                        }

        #endif
                        //convert the yuv420p to rgb565
                        int bytes = 2;//rgb565
                        unsigned char* convm = (unsigned
char*)malloc(PIC_WIDTH*PIC_HEIGHT*bytes);
                        if(convm)
                        {
                        #ifdef ADD_CODEC
                                v4l_yuv420p2rgb (convm, (unsigned
char*)data_for_lcd,PIC_WIDTH, PIC_HEIGHT, bytes*8);
                        #else
                                v4l_yuv420p2rgb (convm, (unsigned
char*)adu->getData(),PIC_WIDTH, PIC_HEIGHT, bytes*8);
                        #endif
                                //display it to frame buffer
                                displayVideo((short*)convm);
                                free(convm);
                        }
                        else
                        {
                                printf("Can not allocate memory\n");
                        }
                        delete adu;
                }
                Thread::sleep(TimerPort::getTimer());
                TimerPort::incTimer(frameSize);
        }
        printf("Quit the video Thread Send/Recv\n");
        free(data_for_lcd);
        free(data_from_wc);
        free( data_compressed);
        free( data_to_send);
}

Do you find any problem? please give me your idea. Thanks!


                                                

-- 
--------------Seven Pham----------------
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.